摘要:事件行為在瀏覽器中保持一次,并且符合標(biāo)準(zhǔn)。主要是進(jìn)行修復(fù)。事件已經(jīng)在移動上支持。阻止已經(jīng)在上存在的事件錯誤處理。然后對應(yīng)的將會被打包送往客戶端。在中棄用,現(xiàn)在正式刪除。是運行于一個嚴(yán)格的安全策略下成為可能。增加警告提示非生產(chǎn)環(huán)境。
??寫在開頭
閱讀React官網(wǎng)的 RECENT POSTS的個人翻譯/摘要(部分)。
英文片段為官網(wǎng)原文片段。
原文地址
??為什么要使用React目前已經(jīng)有很多的JavaScript MVC frameworks出世,但是為什么Facebook需要創(chuàng)建React,并且又是什么原因?qū)е挛覀兿胍ビ盟?/p>
不是一個MVC框架。是一個可用來構(gòu)建組件化用戶界面的庫,同時力挺用于構(gòu)建那些交互數(shù)據(jù)隨時間改變的可復(fù)用的UI組件。
不是模板。傳統(tǒng)的頁面渲染(JavaScript渲染),是使用一些模板工具或者直接使用html標(biāo)簽進(jìn)行:填充+拼接+渲染。這些構(gòu)建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以不同的方式構(gòu)建用戶界面:分隔整個UI為一塊一塊小的UI組件UI Components。這就意味著我們使用一門真實、充滿特色的編程語言來渲染視圖,其優(yōu)于模板渲染有以下幾個原因:
javaScript是一門靈活、強(qiáng)大的編程語言,其擁有構(gòu)建抽象對象的能力。這一點在大型應(yīng)用中非常重要。
通過將標(biāo)記(標(biāo)簽)與相應(yīng)的視圖邏輯統(tǒng)一起來,React能夠更加容易的進(jìn)行擴(kuò)展和維護(hù)視圖。
通過JavaScript code的形式來代替標(biāo)記(標(biāo)簽)和內(nèi)容,這個過程沒有字符拼接的過程并且減少了XSS漏洞。
同時創(chuàng)建了JSX,它是JavaScript的語法擴(kuò)展。如果比如原生的JavaScript,你更喜歡HTML的可讀性,就使用它吧!
不能再簡單的響應(yīng)式數(shù)據(jù)更新當(dāng)你的應(yīng)用數(shù)據(jù)隨著時間變化時,React表現(xiàn)是十分耀眼!
在傳統(tǒng)的JavaScript應(yīng)用中,你需要關(guān)注哪些數(shù)據(jù)變化了并且命令式的改變DOM的狀態(tài),以便保持視圖和數(shù)據(jù)的一致。甚至通過指令和數(shù)據(jù)來提供了一種聲明式界面的AngularJS,也是通過綁定需要的函數(shù)來手動更新DOM節(jié)點。
React采用不同的方法:
當(dāng)組件初始化時調(diào)用render方法,并且生成一個輕量級的視圖表達(dá)式。這個表達(dá)式將會返回一個標(biāo)簽字符串,并且插入頁面文檔中去。
當(dāng)數(shù)據(jù)變化的時候,render方法將被會再次調(diào)用。為了盡可能的提高更新效率,我們把先舊數(shù)據(jù)和新數(shù)據(jù)傳入render方法進(jìn)行對比,生成一個最小的變化來操作DOM。(render方法返回的值不是字符串也不是一個DOM元素,而是一個輕量級的DOM表達(dá)式)。
HTML僅僅只一個開始由于React有著自己的輕量級的文本表達(dá)式,我們可以做一些更酷的事情:
FaceBook使用React代替html繪制canvas動態(tài)圖。
結(jié)合React和Backbone.Rounter可以完美的構(gòu)建單頁應(yīng)用(Instagram)。
我們在React內(nèi)部原理處理,使得React App既能在web上運行,也能通過Objective-C bridge驅(qū)動原生IOS視圖。
You can run React on the server for SEO, performance, code sharing and overall flexibility。
事件行為在瀏覽器中保持一次,并且符合標(biāo)準(zhǔn)。默認(rèn)使用事件代理。
??React v0.3.3我們將在React v0.4中新增了許多中西,但是與此同時我們發(fā)布了React v0.3.3。這個版本解決了人們在使用中遇到的問題,并且使我們的工具更加容易使用。
React允許反復(fù)使用同一個DOMNode渲染不同的組件。
React.renderComponent(, domNode)
React.renderComponent(, domNode)
??New in React v0.4: Prop Validation and Default Values我們收到關(guān)于React問題中,有大部分是關(guān)于props的,特別是人們希望對props進(jìn)行驗證或者使其有個合理的默認(rèn)值。
Validation在使用props之前,我們經(jīng)常對props的某些參數(shù)進(jìn)行某些特殊的處理,例如:需要確定這些屬性是否是特定的類型、需求限定某些值、某些參數(shù)的成分是必須的。這些驗證我們都可以在render里面處理,但是這回使render顯得臃腫!
現(xiàn)在,React v.04帶來的內(nèi)建的驗證模塊,你可以寫你自己的限定
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
在以往的例子里面,我們經(jīng)??吹揭韵麓a:
React.createClass({ render: function() { var value = this.props.value || "default value"; return{value}; } });
如果對幾個穿插在幾個不同組件的props進(jìn)行以上操作,這將會產(chǎn)生大量的冗余代碼。在React v0.04中,你可以以申明的方式提供默認(rèn)值。
React.createClass({ getDefaultProps: function() { return { value: "default value" }; } ... });
在render之前,我們使用這些函數(shù)進(jìn)行處理(我們也會在render之前支持所有的驗證函數(shù)),以保證你在使用的時候拿到的數(shù)據(jù)是你所需要的。
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版本只是進(jìn)行了小小的改動。主要是進(jìn)行修復(fù)。部分代碼在底層修改了,但是這不會影響你調(diào)用我們的公共Api。
ReactsetState的callback參數(shù),會在組件域調(diào)用。
click事件已經(jīng)在移動Safari上支持。
阻止已經(jīng)在Object.prototype上存在的事件錯誤處理。
不用設(shè)置先前就已經(jīng)定義了的DOM屬性為undefined。
優(yōu)化對iframe屬性的支持。
增加checksums屬性來檢測和校驗服務(wù)端渲染和客戶端實際渲染內(nèi)容的是否一致。
JSXTransformer改良環(huán)境檢測機(jī)制,使其能運行在非瀏覽器環(huán)境。
Improved environment detection so it can be run in a non-browser environment.
??Use React and JSX in Python Applications今天我們很高興的宣布PyReact的初始版本的發(fā)布。它使得在你的pyhton應(yīng)用中能夠很好的使用React和JSX。PyReact設(shè)計的宗旨是提供一個轉(zhuǎn)化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 實現(xiàn)了一個完整的react項目react-page。其支持客戶端和服務(wù)端的渲染、使用模板系統(tǒng)進(jìn)行轉(zhuǎn)化和打包、實時重載。
為什么使用服務(wù)端渲染?
提高頁面初始化速度
在下載JavaScript前,一些標(biāo)簽元素將會被展示給用戶。
在服務(wù)端標(biāo)簽元素的構(gòu)建遠(yuǎn)遠(yuǎn)快于客戶端。
更快的開發(fā)和構(gòu)建原型
不用等待任何監(jiān)聽腳本或打包器。
更容易的部署
SEO
服務(wù)端渲染是如何進(jìn)行的?
在服務(wù)端構(gòu)建、發(fā)送標(biāo)簽給客戶端,這樣用戶可以很快的看到內(nèi)容。
然后對應(yīng)的JavaScript將會被打包送往客戶端。
瀏覽器運行對應(yīng)JavaScript,這樣所有的事件句柄、交互、數(shù)據(jù)更新等將會無縫隙的對服務(wù)端生成的標(biāo)記進(jìn)行綁定。
肉眼看來這一切好像都是發(fā)生在客戶端,只是更快。
?? React v0.5 Changelog優(yōu)化內(nèi)存使用:通過使用 GC PAUSES(GC:Garbage Collection,垃圾收集,垃圾回收)機(jī)制,減少核心內(nèi)存分配。
提升性能:為了提供代碼運行速度,我們從V8和Nitro中剔除了一些slow path code。
在網(wǎng)絡(luò)設(shè)備里面區(qū)分不同的路徑是一個很自然的選擇,因為網(wǎng)絡(luò)設(shè)備的首要任務(wù)是轉(zhuǎn)發(fā)網(wǎng)絡(luò)包,不同的網(wǎng)絡(luò)包,在設(shè)備里面的處理路徑不同。fast path就是那些可以依據(jù)已有狀態(tài)轉(zhuǎn)發(fā)的路徑,在這些路徑上,網(wǎng)關(guān),二層地址等都已經(jīng)準(zhǔn)備好了,不需要緩存數(shù)據(jù)包,而是可以直接轉(zhuǎn)發(fā)。slow path是那些需要額外信息的包,比如查找路由,解析MAC地址等。
first path是設(shè)備收到流上第一個包所走過的路徑,比如tcp里面的syn包,有些實現(xiàn)把三次握手都放到first path里面處理,而有些只需處理syn包,其他包就進(jìn)入fast path的處理路徑。
在NP或者ASIC里面也需要區(qū)分slow path和fast path,fast path上的包都放在SRAM里面,而slow path的包放在DRAM里面。不過這也非絕對。決定處理路徑的是對于速度的考慮。處理器的速度,內(nèi)存的速度等。訪問內(nèi)存的速度由速度和帶寬兩個因素決定。因此,把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
標(biāo)準(zhǔn)化支持:DOM屬性的處理。在處理之前不僅有多余的檢查和開銷,而且還是混淆使用者?,F(xiàn)在我們會一直控制你的屬性值為string直到渲染。
支持Selection事件。
支持混合事件(池化喲)。
支持一些額外DOM屬性:charSet, content, form, httpEquiv, rowSpan, autoCapitalize。
支持額外的SVG屬性:rx、ry。
同時支持getInitialState和getDefaultProps。
支持掛載到iframes。
表單組件的bugfix。
增加react.version。
增加react.isValidClass:用戶檢查某個值是否是有效的組件構(gòu)造函數(shù)。
刪除React.autoBind。在React v0.4中棄用,現(xiàn)在正式刪除。
重命名:React.unmountAndReleaseReactRootNode 為 React.unmountComponentAtNode。
開始著手于精細(xì)的性能分析。
更好的支持服務(wù)端渲染。
是React運行于一個嚴(yán)格的安全策略下成為可能。同時使使用React編寫chrome插件成為可能。
JSX屬性class更名問className。
增加警告提示(非生產(chǎn)環(huán)境)。
改善Window兼容性。
?? React v0.9 [RC] Upgrade Notes我們JSX解釋器處理空格上面進(jìn)行了改變。簡單來說就是,在一行上面組件與組件之前的空格將會被保留,而換行(文本節(jié)點或者組件)會被忽略。
Monkeys: {listOfMonkeys} {submitButton}0.8- React.DOM.div(null, " Monkeys: ", listOfMonkeys, submitButton ) 0.9+ React.DOM.div(null, "Monkeys:", listOfMonkeys, " ", submitButton )
相信這個新特性會非常有空,可以有效減少匆忙之中帶來的非期待的空格。
如果你希望保留 后面緊跟換行文本節(jié)點 后面的空格,那么你可以在JSX里面使用這種寫法:{"Monkeys: }。
?? The Road to 1.0 (2014-03-28)我們在去年春天發(fā)布了React,但是我們卻有意的沒有發(fā)布版本React v1.0。其實我們已經(jīng)做好了生產(chǎn)準(zhǔn)備,但是我們計劃在內(nèi)部和外部根據(jù)開發(fā)者怎么使用React來發(fā)展API和行為特性。在過去的九個月我們學(xué)到了很多,并且思考很多關(guān)于1.0對于React意味著什么。在過去的兩周內(nèi),我在多個項目里面概述了我們打算進(jìn)入1.0+的世界。今天我書寫一點點給我們的用戶,以便用戶更好的了解我們的計劃。
我們在1.0中主要的目的是闡明我們的消息模式,并且聚焦在一個與我們目的相關(guān)的API上面進(jìn)行處理。為了完成這個目的,我們清除一些已經(jīng)遇到的不友好的模式,真正的幫助開發(fā)者寫出更好的代碼。
ES6在我們正式推出React之前,我們就思考過如何在React里面利用ES6,即類,以此來提高創(chuàng)建React組件的體驗。我們覺得使用 React.createClass(…) 不是一個最好的選擇。即使在使用方面優(yōu)劣性沒有正確的答案,但是我們在向ES6方面靠攏。我們希望確保這個過程盡可能的簡單。例如:
class MyComponent extends React.Component { render() { ... } }
其他一些ES6的特性我們在React核心使用了。確信后面會有更多的特性加入。
JSX在ES6方面的支持我們已經(jīng)在react-tools里面搭船上線。已經(jīng)支持轉(zhuǎn)化大部分的ES6代碼轉(zhuǎn)換為老瀏覽器支持的代碼。
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() 調(diào)用的時候調(diào)用一次,替代原來每次組件渲染時調(diào)用。這就意味著 getDefaultProps() 不會改變他的返回值,同時任何對象將會在所有實例中共享。這個改變提示了性能,并且使得將來能夠更早的在渲染中做 PropTypes check ,這將使我們能夠給出更好的錯誤提示。
Rendering to null自從React發(fā)布以來,開發(fā)者基本都遇到過 render nothing 的情況。通常是返回一個空或者。有些更聰明的人返回來避免不要的DOM nodes。我們對此提供了一個解決辦法:return null 。這樣能夠進(jìn)一步幫忙開發(fā)者寫出有意義的代碼。在實現(xiàn)上,我們使用了標(biāo)簽進(jìn)行處理,盡管我們目的是不返回任何東西。因為noscript并不會影響你的布局,所以你可以放心使用。
// Before render: function() { if (!this.state.visible) { return ; } // ... } // After render: function() { if (!this.state.visible) { return null; } // ... }JSX Namespacing
在JSX里面支持namespaceing呼喊我們已經(jīng)聽到了很長一段時間??紤]到JSX是JavaScript實現(xiàn)的,所以我們不愿意使用XML namespaceing。相反,我們使用選擇JavaScript標(biāo)準(zhǔn)來實現(xiàn): 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
根據(jù)DOM3,React鍵盤事件包含了一個標(biāo)準(zhǔn)化的 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鍵盤事件和鼠標(biāo)事件也包含了標(biāo)準(zhǔn)化的 e.getModifierState() 。
?? Flux: Actions and the DispatcherFlux是Facebook構(gòu)建JavaScript應(yīng)用的時候使用的基于單項數(shù)據(jù)流的應(yīng)用框架。我們使用Flux的構(gòu)建大型應(yīng)用都是有小的組件組成,Flux來控制我們提供的小組件(們)。我們找到了一個非常棒的代碼組織結(jié)構(gòu),我們十分激動的分享到開源社區(qū)。
比如一個完整的框架,Flux更像一種模式,讓你不用增加太多新代碼就能夠使用Flux。直到最近的,我們還沒有發(fā)布Flux模塊之一: dispatcher。但是隨著新的Flux code項目和Flux website發(fā)布,我們提供我們在生產(chǎn)項目中使用的dispatcher。
Where the Dispatcher Fits in the Flux Data Flowdispatcher是一個單例。作為數(shù)據(jù)控制中心控制Flux應(yīng)用的數(shù)據(jù)流。簡單的來說,他就是提供注冊回調(diào)函數(shù),然后使用一定的命令調(diào)用這些回調(diào)函數(shù)。每個store都通過dispatcher注冊了回調(diào)。當(dāng)dispatcher中有新數(shù)據(jù)來,它使用這些回調(diào)通知相應(yīng)的store。然后相關(guān)程序通過dispatch()啟動回調(diào)函數(shù)。
Actions and ActionCreators無論是用戶進(jìn)行界面操作還是接口返回的新數(shù)據(jù)進(jìn)入系統(tǒng)的時候,這些數(shù)據(jù)將會被打包送入一個 action(由內(nèi)容和action type組成的對象)。對此,我們常常創(chuàng)建名為ActionCreateors的輔助庫,用來創(chuàng)建action object和傳遞action給dispatcher。
不同的actioins由一個type屬性定義。當(dāng)所有的stores收到action的時候,它們就使用這個屬性來決定怎么響應(yīng)它。在Flux應(yīng)用中,stores和views彼此自我控制,它們不會被外部影響。操作流通過stores定義注冊的回調(diào)進(jìn)入store, not through setter methods。
使stores自我更新能夠避免很多一些MVC應(yīng)用的復(fù)雜情況,例如:各個models之間的聯(lián)合更新會導(dǎo)致狀態(tài)的不穩(wěn)定并且會導(dǎo)致測試非常困難。objects在Flux應(yīng)用中高度分離,并且嚴(yán)格準(zhǔn)守得墨忒耳定律。這樣會導(dǎo)致軟件更加可維護(hù)、適配、測試以及對新工程師來誰更加容易理解。
Why We Need a Dispatcher隨著應(yīng)用的壯大,不同stores之間的依賴必然存在。例如:Store A 必須 Store A 先更新,然后 Store A才知道如何去更新自己。這個時候我們就需要dispatcher能夠調(diào)用 Store B的回調(diào),之后再操作Store A。為了申明這種依賴,Store A 需要告訴dispatcher,我需要等待Store B完成后才能執(zhí)行這個action。dispatcher通過 waitFor()提供這樣的功能。
dispatch()方法通過回調(diào)函數(shù)提供了一個簡單的、同步迭代功能:依次調(diào)用。當(dāng)waitFor()在某一個回調(diào)中觸發(fā),隨后停止執(zhí)行這個回調(diào)函數(shù),并且 waitFor()將提供我們一個有關(guān)依賴的新的迭代周期。等這些依賴執(zhí)行完以后,回調(diào)函數(shù)再繼續(xù)執(zhí)行。
更者,waitFor()方法可是在同一個store中不不同的actions間調(diào)用。
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。
我們?yōu)榱耸剐掠脩舾唵蔚牧私?b>DOM(和React的不同之處)。我們使用術(shù)語ReactElement代替<>,同樣ReactNode代替renderable。
Creating a ReactElement我們提供一個API來創(chuàng)建ReactElement。
var reactElement = React.createElement(type,props,children);
type參數(shù)可以使HTML tag或者class。它指示著什么樣的HTML tag或者class將被渲染和包含哪些props數(shù)據(jù)。你也可以只提供一個type參數(shù)創(chuàng)建一個工程函數(shù)。
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轉(zhuǎn)化器,這個升級將會非常簡單。
// If you use node/browserify modules make sure // that you require React into scope. var React = require("react");
React的JSX將會為你創(chuàng)建ReactElement。
var MyComponent = React.createClass(...); var MyOtherComponent = React.createClass({ render: function() { return; } });
React Without JSX
在不使用JSX情況下需要調(diào)用一個組件作為函數(shù),在調(diào)用前你需要明確的創(chuàng)建一個工程函數(shù)。
var MyComponentClass = React.createClass(...); var MyComponent = React.createFactory(MyComponentClass); // New step var MyOtherComponent = React.createClass({ render: function() { return MyComponent({ prop: "value" }); } });
React為常見的HTML elements內(nèi)置了工廠函數(shù)。
var MyDOMComponent = React.createClass({ render: function() { return React.DOM.div({ className: "foo" }); // still ok } });The Next Step: ES6 Classes
在v0.12版本后,我們的工作將轉(zhuǎn)向ES6 classes。我們會保持向后兼容(React.createclass)。如果你已經(jīng)在使用ES6轉(zhuǎn)譯器,你可以按照下面申明你的組件。
export class MyComponent { render(){ ... } };??Deprecating JSTransform and react-tools
隨著JavaScript的發(fā)展,JSTransform有點"跟不上時代",Babel的出現(xiàn)可以完全將其替代。v0.14以后將不會再維護(hù)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