很多等待已久的特性:
包括: fragments, error boundaries, portals, 支持 custom DOM attributes, 改進 server-side rendering, reduced file size
render
方法可以返回新類型: fragments
and strings
現在組件的 render
方法里可以直接返回數組。像在其它地方使用數組一樣,這里每個數組元素也要加上key
屬性。
render() {
return [
// Don't forget the keys :)
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}
注:
fragments
實際指的就是array
, 在這之前如果你想簡單返回一個array
, 不好意思,不行!
上面的代碼會爆這個錯誤 Adjacent XJS elements must be wrapped in an enclosing tag.
現在返回array
時還是要加key屬性,接下來React Team會讓JSX
支持一種不需要key
的fragment
語法。
另外直接返回string
也是支持的, 完整的 render
返回類型可參考.
render() {
return 'Look ma, no spans!';
}
更好的錯誤處理
在之前,渲染時發生的runtime errors
會令React處于異常狀態, 同時產生一些莫名其妙的錯誤消息,只有通過刷新整個頁面才能恢復。React 16采取了一種更靈活的策略來處理這個問題。默認情況下,如果在組件的render
或lifecycle
方法中拋出了錯誤,整個組件樹會從根節點被unmount下來。這樣做的好處是,已經被破壞的數據不會被顯示出來,但帶來的用戶體驗并不理想。
除了把整個app在每次出錯時都unmount
下來,你還可以使用error boundaries. 每一個boundaries都是特殊的React組件,它可以捕獲它子樹的里發生的錯誤,并在它控制區域中顯示一個fallback UI,可以把它想像成傳統的try-catch
語句,但僅用于React組件。
如果要了解更多細節,請看previous post on error handling in React 16.
Portals
Portals
提供了一種最直接的方式去把一個子組件渲染到父組件所控制的DOM樹之外的節點。
render() {
// React does *not* create a new div. It renders the children into `domNode`.
// `domNode` is any valid DOM node, regardless of its location in the DOM.
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}
注:最直接的應用就是用來實現像modal, tooltip之類的組件,這些組件的DOM元素通常會直接被放到頂層,但邏輯上它們又可能只是屬于某個子組件的。
還有一點要特別留意的是,在用Portal的時候,你只是把DOM渲染到父組件之外,但子組件(就是調用Portal那個)還是在React的父組件之內,就是React的組件樹結構不變,不受Portal的調用(或者說DOM結構)影響。
帶來的一個特性就是,你在子組件產生的event會被你的React父組件所捕獲,即使在DOM中,它不是你的父組件。對組件的組織,代碼的切割來所,這應該是個好特性,但如果你同時操作 DOM的話,可能會需要一些特殊處理
更好的服務器端渲染
React 16 里把服務器渲染(SSR)徹底重寫了一遍。新的實現非常快,并且支持 streaming, 現在你可以更快地把渲染的字節發送到客戶端。
多虧了在 新的打包策略 中去掉了process.env
檢查(信不信由你, 在node.js
里讀取process.env
真的很慢),現在你不再需要在服務器端重新打包一次React也可以有不錯的服務端渲染性能。
核心小組的Sasha Aickin寫了一篇很棒的文章來闡述React 16里的改進
. 根據 Sasha's 的模擬benchmarks
, React 16里的服務端渲染性能 3倍于React 15.
"When comparing against React 15 with process.env compiled out, there’s about a 2.4x improvement in Node 4, about a 3x performance improvement in Node 6, and a full 3.8x improvement in the new Node 8.4 release. And if you compare against React 15 without compilation, React 16 has a full order of magnitude gain in SSR in the latest version of Node!" (As Sasha points out, please be aware that these numbers are based on synthetic benchmarks and may not reflect real-world performance.)
另外,React 16在hydrating
(注:指在客戶端基于服務器返回的HTML再次重新渲染)方面也表現的更好。React 16
不再要求客戶端的初始渲染完全和服務器返回的渲染結果一致,而是盡量重用已經存在的DOM元素。不再會有checkusm!
一般來說,在服務器和客戶端渲染不同的內容是不建議的,但這樣做在某些情況下也是有用的(比如,生成timestamp).
documentation for ReactDOMServer
有更多細節可供參考
支持自定義DOM屬性
React不再忽略無法識別的HTML和SVG屬性,現在它會把這些屬性直接傳遞給DOM. 這個改動讓React可以去掉屬性白名單,從而減小了文件大小
縮減文件大小
盡管添加了這些新特性, React 16 實際上比 15.6.1還要苗條
react is 5.3 kb (2.2 kb gzipped), down from 20.7 kb (6.9 kb gzipped).
react-dom is 103.7 kb (32.6 kb gzipped), down from 141 kb (42.9 kb gzipped).
react + react-dom is 109 kb (34.8 kb gzipped), down from 161.7 kb (49.8 kb gzipped).
總體上就是比上個版本減小了 32% (30% post-gzip).
文件尺寸的減小一部分要歸功于打包方法的改變。
React now uses Rollup to create flat bundles for each of its different target formats, resulting in both size and runtime performance wins. The flat bundle format also means that React's impact on bundle size is roughly consistent regardless of how your ship your app, whether it's with Webpack, Browserify, the pre-built UMD bundles, or any other system.
MIT licensed
如果你沒有讀過,點我, React 16 現在使用MIT license. 為了那些不能立刻升級React的同志們,我們也用MIT發布了React 15.6.2。
新的核心架構
React 16 是第一個使用新架構Fiber的版本。你可以在這里了解所有詳情
(劇透一下: 我們重寫了React!)
大部分的新特性,像error boundaries, fragments,都可以歸功于Fiber。接下來的發布的版本,你們可以期待更多的新特性,因為我們要釋放React的所有潛能。
最令人興奮的大概就是異步渲染。
通過異步渲染, 程序可以更流暢地運行,因為React可以避免阻塞主線程。