摘要:事件行为在浏览器中保持一次,并且符合标准。主要是进行修复。事件已经在移动上支持。阻止已经在上存在的事件错误处理。然后对应的将会被打包送往客户端。在中弃用,现在正式删除。是运行于一个严格的安全策略下成为可能。增加警告提示非生产环境。
⭐️写在开头
阅读React官网的 RECENT POSTS的个人翻译/摘要(部分)。
英文片段为官网原文片段。
原文地址
⭐️为什么要使用React目前已经有很多的JavaScript MVC frameworks出世,但是为什么Facebook需要创建React,并且又是什么原因导致我们想要去用它?
不是一个MVC框架。是一个可用来构建组件化用户界面的库,同时力挺用于构建那些交互数据随时间改变的可复用的UI组件。
不是模板。传统的页面渲染(JavaScript渲染),是使用一些模板工具或者直接使用html标签进行:填充+拼接+渲染。这些构建UI的模板整体抽象了你想要的。
Traditionally, web application UIs are built using templates or HTML directives. These templates dictate the full set of abstractions that you are allowed to use to build your UI.
React以不同的方式构建用户界面:分隔整个UI为一块一块小的UI组件UI Components。这就意味着我们使用一门真实、充满特色的编程语言来渲染视图,其优于模板渲染有以下几个原因:
javaScript是一门灵活、强大的编程语言,其拥有构建抽象对象的能力。这一点在大型应用中非常重要。
通过将标记(标签)与相应的视图逻辑统一起来,React能够更加容易的进行扩展和维护视图。
通过JavaScript code的形式来代替标记(标签)和内容,这个过程没有字符拼接的过程并且减少了XSS漏洞。
同时创建了JSX,它是JavaScript的语法扩展。如果比如原生的JavaScript,你更喜欢HTML的可读性,就使用它吧!
不能再简单的响应式数据更新当你的应用数据随着时间变化时,React表现是十分耀眼!
在传统的JavaScript应用中,你需要关注哪些数据变化了并且命令式的改变DOM的状态,以便保持视图和数据的一致。甚至通过指令和数据来提供了一种声明式界面的AngularJS,也是通过绑定需要的函数来手动更新DOM节点。
React采用不同的方法:
当组件初始化时调用render方法,并且生成一个轻量级的视图表达式。这个表达式将会返回一个标签字符串,并且插入页面文档中去。
当数据变化的时候,render方法将被会再次调用。为了尽可能的提高更新效率,我们把先旧数据和新数据传入render方法进行对比,生成一个最小的变化来操作DOM。(render方法返回的值不是字符串也不是一个DOM元素,而是一个轻量级的DOM表达式)。
HTML仅仅只一个开始由于React有着自己的轻量级的文本表达式,我们可以做一些更酷的事情:
FaceBook使用React代替html绘制canvas动态图。
结合React和Backbone.Rounter可以完美的构建单页应用(Instagram)。
我们在React内部原理处理,使得React App既能在web上运行,也能通过Objective-C bridge驱动原生IOS视图。
You can run React on the server for SEO, performance, code sharing and overall flexibility。
事件行为在浏览器中保持一次,并且符合标准。默认使用事件代理。
⭐️React v0.3.3我们将在React v0.4中新增了许多中西,但是与此同时我们发布了React v0.3.3。这个版本解决了人们在使用中遇到的问题,并且使我们的工具更加容易使用。
React允许反复使用同一个DOMNode渲染不同的组件。
React.renderComponent(, domNode)
React.renderComponent(, domNode)
⭐️New in React v0.4: Prop Validation and Default Values我们收到关于React问题中,有大部分是关于props的,特别是人们希望对props进行验证或者使其有个合理的默认值。
Validation在使用props之前,我们经常对props的某些参数进行某些特殊的处理,例如:需要确定这些属性是否是特定的类型、需求限定某些值、某些参数的成分是必须的。这些验证我们都可以在render里面处理,但是这回使render显得臃肿!
现在,React v.04带来的内建的验证模块,你可以写你自己的限定
React.createClass({ propTypes: { // An optional string prop named "description". description: React.PropTypes.string, // A required enum prop named "category". category: React.PropTypes.oneOf(["News","Photos"]).isRequired, // A prop named "dialog" that requires an instance of Dialog. dialog: React.PropTypes.instanceOf(Dialog).isRequired }, ... });Default Values
在以往的例子里面,我们经常看到以下代码:
React.createClass({ render: function() { var value = this.props.value || "default value"; return{value}; } });
如果对几个穿插在几个不同组件的props进行以上操作,这将会产生大量的冗余代码。在React v0.04中,你可以以申明的方式提供默认值。
React.createClass({ getDefaultProps: function() { return { value: "default value" }; } ... });
在render之前,我们使用这些函数进行处理(我们也会在render之前支持所有的验证函数),以保证你在使用的时候拿到的数据是你所需要的。
Both of these features are entirely optional. We"ve found them to be increasingly valuable at Facebook as our applications grow and evolve, and we hope others find them useful as well.
⭐️React v0.4.1React v0.4.1版本只是进行了小小的改动。主要是进行修复。部分代码在底层修改了,但是这不会影响你调用我们的公共Api。
ReactsetState的callback参数,会在组件域调用。
click事件已经在移动Safari上支持。
阻止已经在Object.prototype上存在的事件错误处理。
不用设置先前就已经定义了的DOM属性为undefined。
优化对iframe属性的支持。
增加checksums属性来检测和校验服务端渲染和客户端实际渲染内容的是否一致。
JSXTransformer改良环境检测机制,使其能运行在非浏览器环境。
Improved environment detection so it can be run in a non-browser environment.
⭐️Use React and JSX in Python Applications今天我们很高兴的宣布PyReact的初始版本的发布。它使得在你的pyhton应用中能够很好的使用React和JSX。PyReact设计的宗旨是提供一个转化JSX为JavaScript的API。
Usage:show me codefrom react import jsx # For multiple paths, use the JSXTransformer class. transformer = jsx.JSXTransformer() for jsx_path, js_path in my_paths: transformer.transform(jsx_path, js_path) # For a single file, you can use a shortcut method. jsx.transform("path/to/input/file.jsx", "path/to/output/file.js")Django:support the pip
#install $ pip install PyReact #use PIPELINE_COMPILERS = ( "react.utils.pipeline.JSXCompiler",)React Page
Jordan Walke 实现了一个完整的react项目react-page。其支持客户端和服务端的渲染、使用模板系统进行转化和打包、实时重载。
为什么使用服务端渲染?
提高页面初始化速度
在下载JavaScript前,一些标签元素将会被展示给用户。
在服务端标签元素的构建远远快于客户端。
更快的开发和构建原型
不用等待任何监听脚本或打包器。
更容易的部署
SEO
服务端渲染是如何进行的?
在服务端构建、发送标签给客户端,这样用户可以很快的看到内容。
然后对应的JavaScript将会被打包送往客户端。
浏览器运行对应JavaScript,这样所有的事件句柄、交互、数据更新等将会无缝隙的对服务端生成的标记进行绑定。
肉眼看来这一切好像都是发生在客户端,只是更快。
⭐️ React v0.5 Changelog优化内存使用:通过使用 GC PAUSES(GC:Garbage Collection,垃圾收集,垃圾回收)机制,减少核心内存分配。
提升性能:为了提供代码运行速度,我们从V8和Nitro中剔除了一些slow path code。
在网络设备里面区分不同的路径是一个很自然的选择,因为网络设备的首要任务是转发网络包,不同的网络包,在设备里面的处理路径不同。fast path就是那些可以依据已有状态转发的路径,在这些路径上,网关,二层地址等都已经准备好了,不需要缓存数据包,而是可以直接转发。slow path是那些需要额外信息的包,比如查找路由,解析MAC地址等。
first path是设备收到流上第一个包所走过的路径,比如tcp里面的syn包,有些实现把三次握手都放到first path里面处理,而有些只需处理syn包,其他包就进入fast path的处理路径。
在NP或者ASIC里面也需要区分slow path和fast path,fast path上的包都放在SRAM里面,而slow path的包放在DRAM里面。不过这也非绝对。决定处理路径的是对于速度的考虑。处理器的速度,内存的速度等。访问内存的速度由速度和带宽两个因素决定。因此,把SRAM放到fast path上,也是很自然的选择。
fast path: Frontend -> simple code generator -> assembler
slow path: Frontend -> IR optimizer (sometimes more than one level of IR) -> code-generator -> assembler
标准化支持:DOM属性的处理。在处理之前不仅有多余的检查和开销,而且还是混淆使用者。现在我们会一直控制你的属性值为string直到渲染。
支持Selection事件。
支持混合事件(池化哟)。
支持一些额外DOM属性:charSet, content, form, httpEquiv, rowSpan, autoCapitalize。
支持额外的SVG属性:rx、ry。
同时支持getInitialState和getDefaultProps。
支持挂载到iframes。
表单组件的bugfix。
增加react.version。
增加react.isValidClass:用户检查某个值是否是有效的组件构造函数。
删除React.autoBind。在React v0.4中弃用,现在正式删除。
重命名:React.unmountAndReleaseReactRootNode 为 React.unmountComponentAtNode。
开始着手于精细的性能分析。
更好的支持服务端渲染。
是React运行于一个严格的安全策略下成为可能。同时使使用React编写chrome插件成为可能。
JSX属性class更名问className。
增加警告提示(非生产环境)。
改善Window兼容性。
⭐️ React v0.9 [RC] Upgrade Notes我们JSX解释器处理空格上面进行了改变。简单来说就是,在一行上面组件与组件之前的空格将会被保留,而换行(文本节点或者组件)会被忽略。
Monkeys: {listOfMonkeys} {submitButton}0.8- React.DOM.div(null, " Monkeys: ", listOfMonkeys, submitButton ) 0.9+ React.DOM.div(null, "Monkeys:", listOfMonkeys, " ", submitButton )
相信这个新特性会非常有空,可以有效减少匆忙之中带来的非期待的空格。
如果你希望保留 后面紧跟换行文本节点 后面的空格,那么你可以在JSX里面使用这种写法:{"Monkeys: }。
⭐️ The Road to 1.0 (2014-03-28)我们在去年春天发布了React,但是我们却有意的没有发布版本React v1.0。其实我们已经做好了生产准备,但是我们计划在内部和外部根据开发者怎么使用React来发展API和行为特性。在过去的九个月我们学到了很多,并且思考很多关于1.0对于React意味着什么。在过去的两周内,我在多个项目里面概述了我们打算进入1.0+的世界。今天我书写一点点给我们的用户,以便用户更好的了解我们的计划。
我们在1.0中主要的目的是阐明我们的消息模式,并且聚焦在一个与我们目的相关的API上面进行处理。为了完成这个目的,我们清除一些已经遇到的不友好的模式,真正的帮助开发者写出更好的代码。
ES6在我们正式推出React之前,我们就思考过如何在React里面利用ES6,即类,以此来提高创建React组件的体验。我们觉得使用 React.createClass(…) 不是一个最好的选择。即使在使用方面优劣性没有正确的答案,但是我们在向ES6方面靠拢。我们希望确保这个过程尽可能的简单。例如:
class MyComponent extends React.Component { render() { ... } }
其他一些ES6的特性我们在React核心使用了。确信后面会有更多的特性加入。
JSX在ES6方面的支持我们已经在react-tools里面搭船上线。已经支持转化大部分的ES6代码转换为老浏览器支持的代码。
Context尽管我们没有在文档中提及过context,但是它以某种形式在React确切存在的。
While we haven"t documented context, it exists in some form in React already. It exists as a way to pass values through a tree without having to use props at every single point. We"ve seen this need crop up time and time again, so we want to make this as easy as possible. Its use has performance tradeoffs, and there are known weaknesses in our implementation, so we want to make sure this is a solid feature.
⭐️ React v0.11 getDefaultProps从React0.11开始,getDefaultProps()只会在 React.createClass() 调用的时候调用一次,替代原来每次组件渲染时调用。这就意味着 getDefaultProps() 不会改变他的返回值,同时任何对象将会在所有实例中共享。这个改变提示了性能,并且使得将来能够更早的在渲染中做 PropTypes check ,这将使我们能够给出更好的错误提示。
Rendering to null自从React发布以来,开发者基本都遇到过 render nothing 的情况。通常是返回一个空或者。有些更聪明的人返回来避免不要的DOM nodes。我们对此提供了一个解决办法:return null 。这样能够进一步帮忙开发者写出有意义的代码。在实现上,我们使用了标签进行处理,尽管我们目的是不返回任何东西。因为noscript并不会影响你的布局,所以你可以放心使用。
// Before render: function() { if (!this.state.visible) { return ; } // ... } // After render: function() { if (!this.state.visible) { return null; } // ... }JSX Namespacing
在JSX里面支持namespaceing呼喊我们已经听到了很长一段时间。考虑到JSX是JavaScript实现的,所以我们不愿意使用XML namespaceing。相反,我们使用选择JavaScript标准来实现: object property access。替代为每个组件分配一个对象,你可以直接这样使用
// Before var UI = require("UI"); var UILayout = UI.Layout; var UIButton = UI.Button; var UILabel = UI.Label; render: function() { returnImproved keyboard event normalization; } // After var UI = require("UI"); render: function() { return text ; } text
根据DOM3,React键盘事件包含了一个标准化的 e.key ,这样允许你在代码中编写一个简单的key,并且能够在所有浏览器运行。
handleKeyDown: function(e) { if (e.key === "Enter") { // Handle enter key } else if (e.key === " ") { // Handle spacebar } else if (e.key === "ArrowLeft") { // Handle left arrow } }
React键盘事件和鼠标事件也包含了标准化的 e.getModifierState() 。
⭐️ Flux: Actions and the DispatcherFlux是Facebook构建JavaScript应用的时候使用的基于单项数据流的应用框架。我们使用Flux的构建大型应用都是有小的组件组成,Flux来控制我们提供的小组件(们)。我们找到了一个非常棒的代码组织结构,我们十分激动的分享到开源社区。
比如一个完整的框架,Flux更像一种模式,让你不用增加太多新代码就能够使用Flux。直到最近的,我们还没有发布Flux模块之一: dispatcher。但是随着新的Flux code项目和Flux website发布,我们提供我们在生产项目中使用的dispatcher。
Where the Dispatcher Fits in the Flux Data Flowdispatcher是一个单例。作为数据控制中心控制Flux应用的数据流。简单的来说,他就是提供注册回调函数,然后使用一定的命令调用这些回调函数。每个store都通过dispatcher注册了回调。当dispatcher中有新数据来,它使用这些回调通知相应的store。然后相关程序通过dispatch()启动回调函数。
Actions and ActionCreators无论是用户进行界面操作还是接口返回的新数据进入系统的时候,这些数据将会被打包送入一个 action(由内容和action type组成的对象)。对此,我们常常创建名为ActionCreateors的辅助库,用来创建action object和传递action给dispatcher。
不同的actioins由一个type属性定义。当所有的stores收到action的时候,它们就使用这个属性来决定怎么响应它。在Flux应用中,stores和views彼此自我控制,它们不会被外部影响。操作流通过stores定义注册的回调进入store, not through setter methods。
使stores自我更新能够避免很多一些MVC应用的复杂情况,例如:各个models之间的联合更新会导致状态的不稳定并且会导致测试非常困难。objects在Flux应用中高度分离,并且严格准守得墨忒耳定律。这样会导致软件更加可维护、适配、测试以及对新工程师来谁更加容易理解。
Why We Need a Dispatcher随着应用的壮大,不同stores之间的依赖必然存在。例如:Store A 必须 Store A 先更新,然后 Store A才知道如何去更新自己。这个时候我们就需要dispatcher能够调用 Store B的回调,之后再操作Store A。为了申明这种依赖,Store A 需要告诉dispatcher,我需要等待Store B完成后才能执行这个action。dispatcher通过 waitFor()提供这样的功能。
dispatch()方法通过回调函数提供了一个简单的、同步迭代功能:依次调用。当waitFor()在某一个回调中触发,随后停止执行这个回调函数,并且 waitFor()将提供我们一个有关依赖的新的迭代周期。等这些依赖执行完以后,回调函数再继续执行。
更者,waitFor()方法可是在同一个store中不不同的actions间调用。
Problems arise, however, if we have circular dependencies. That is, if Store A needs to wait for Store B, and Store B needs to wait for Store A, we could wind up in an endless loop. The dispatcher now available in the Flux repo protects against this by throwing an informative error to alert the developer that this problem has occurred. The developer can then create a third store and resolve the circular dependency.
⭐️Introducing React ElementsIf you currently use JSX everywhere, you don"t really have to do anything to get these benefits! The updated transformer will do it for you.
If you can"t or don"t want to use JSX, then please insert some hints for us. Add a React.createFactory call around your imported class when you require it。
我们为了使新用户更简单的了解DOM(和React的不同之处)。我们使用术语ReactElement代替<>,同样ReactNode代替renderable。
Creating a ReactElement我们提供一个API来创建ReactElement。
var reactElement = React.createElement(type,props,children);
type参数可以使HTML tag或者class。它指示着什么样的HTML tag或者class将被渲染和包含哪些props数据。你也可以只提供一个type参数创建一个工程函数。
var div = React.createFactory("div"); var reactDivElement = div(props,children);
React Element的签名就像这样
{ type : string | class, props : { children, className, etc. }, key : string | boolean | number | null, ref : string | null }Upgrading to 0.12
React With JSX
如果你使用React的JSX转化器,这个升级将会非常简单。
// If you use node/browserify modules make sure // that you require React into scope. var React = require("react");
React的JSX将会为你创建ReactElement。
var MyComponent = React.createClass(...); var MyOtherComponent = React.createClass({ render: function() { return; } });
React Without JSX
在不使用JSX情况下需要调用一个组件作为函数,在调用前你需要明确的创建一个工程函数。
var MyComponentClass = React.createClass(...); var MyComponent = React.createFactory(MyComponentClass); // New step var MyOtherComponent = React.createClass({ render: function() { return MyComponent({ prop: "value" }); } });
React为常见的HTML elements内置了工厂函数。
var MyDOMComponent = React.createClass({ render: function() { return React.DOM.div({ className: "foo" }); // still ok } });The Next Step: ES6 Classes
在v0.12版本后,我们的工作将转向ES6 classes。我们会保持向后兼容(React.createclass)。如果你已经在使用ES6转译器,你可以按照下面申明你的组件。
export class MyComponent { render(){ ... } };⭐️Deprecating JSTransform and react-tools
随着JavaScript的发展,JSTransform有点"跟不上时代",Babel的出现可以完全将其替代。v0.14以后将不会再维护JSTransform和react-tools(react-tools has always been a very thin wrapper around JSTransform.),React和React Native目前都使用三方的Babel的JSX编译器处理.
Other Deprecationsesprima-fb
ECMAScript解析器
JSXTransformer
JSXTransformer is another tool we built specifically for consuming JSX in the browser. It was always intended as a quick way to prototype code before setting up a build process. It would look for