英語原文:React v16.0 (Sep 26, 2017)
我們很高興的宣布React v16.0發布了! 這個版本包含了很多長期被使用者期待的功能,包括:
- fragments (返回片段類型)
- error boundaries(處理錯誤)
- portals (掛載方式)
- custom DOM attributes (支持自定義DOM屬性)
- improved server-side rendering (提升服務端渲染性能)
- reduced file size (減少react庫文件大小)
下面逐一說明
render函數可返回新的類型:數組和字符串
新的版本支持組件的render方法返回包含元素的數組類型,代碼如下:
render() {
//不需要再把所有的元素綁定到一個單獨的元素中了
return [
// 別忘記加上key值
<li key="A"/>First item</li>,
<li key="B"/>Second item</li>,
<li key="C"/>Third item</li>,
];
}
關于render()方法的詳細說明,請查看API文檔。
更好的錯誤處理
之前的React,在渲染過程中如果遇到運行時的錯誤,可能會導致整個React組件的崩潰,并產生一些隱藏的錯誤信息,需要重新刷新才能恢復。為了解決這個問題,React 16 使用了一個更有彈性的錯誤處理策略。默認情況下,如果一個錯誤是在組件的渲染或者生命周期方法中被拋出,整個組件結構就會從根節點中卸載。這種方式阻礙了損壞數據的展示,但不是很好的用戶體驗。
新的策略:對于這種一出現錯誤就卸載整個組件app的方式進行了改善,你可以使用error boundaries(錯誤邊界)來進行處理,它是專門用來抓取其下子組件錯誤并向視圖展示錯誤信息的組件。將error boundaries(錯誤邊界)想象成 try { } catch() { } 語句,只不過它是React專用而已。
想要了解更多關于這個特性的說明,請查看這篇文章。
掛載方式
Portals(掛載方式)提供了一個非常好的方式,可以將渲染的children插入到一個DOM節點,而這個節點可以是存在于當前組件DOM結構外的其他節點。
render() {
// 可以不必創建一個新的div標簽,divNode是一個存在于dom結構的節點,不需要考慮這個節點的位置
return React.createPortal(
this.props.children,
divNode,
);
}
更好的服務端渲染
React 16更好的支持服務端HTML的渲染,不再需要服務端進行初始化渲染以匹配結果了,它會嘗試重新利用盡可能多的已存在DOM節點。
為了支持流,服務端渲染器被完全重寫。React的核心成員Sasha Aicken,它是這個功能的貢獻者,寫了一篇非常好的文章來描述React 16 SSR的提升?!颁秩玖鞯姆绞侥軌驕p少獲取響應首字節前所花費的毫秒數(TTFB),將頁面文檔的開頭沿著電纜發送到瀏覽器端時,下一部分的頁面文檔已經形成了。用這種流的方式,所有的主流瀏覽器都會更早的開始解析和渲染頁面文檔”。
支持自定義的DOM屬性
取代之前忽略不識別的HTML和SVG屬性的方式,新的版本將會把它們傳遞給DOM元素。這個新特性會讓我們擺脫可用的React屬性白名單,從而減少文件的大小。
可以參考文章:DOM Attributes in React 16
減少文件體積
除了上面提交到的這些特性,React16要比v15.6.1更小!
- react 大小從之前的20.7kb(壓縮后6.9kb)降低到現在的5.3kb (壓縮后2.2kb)。
- react-dom 從之前的141kb(壓縮后42.9kb)降低到現在的103.7kb(壓縮后32.6kb)。
- react + react-dom 從之前的161.7kb(壓縮后49.8kb)到現在的109kb(壓縮后43.8kb)。
文件大小的變化部分歸功于打包工具的改變。React現在使用Rollup針對不同的目標格式創建打包,進而使文件大小和運行時性能都表現優秀。
新的核心架構
React 16是React第一個建立在一個稱為"Fiber"全新架構的版本。你可以通過閱讀Facebook的工程博客了解Fiber全部的內容。
這個版本中的大部分功能,比如error boundaries和fragments,這都是通過重寫和核心架構來實現這些可能的。而事后的幾個版本中,你能夠回去更多的新特性,因為我們會開始全力釋放React的全部潛能。
也許最讓人興奮的地方是我們正致力于async rendering(異步渲染)的工作 —— 這個策略能通過周期性的向瀏覽器發布執行任務從而協同調度渲染工作。結果就是使用異步渲染,應用將會更加響應式,因為React避免了主線程的阻塞。
我們認為異步渲染是一個充滿意義的功能,它代表了React的未來。為了能夠保證現有項目平滑的融合v16.0版本,這個版本我們并沒有啟動任何異步的特性,但是在接下來的幾個月里我們會非常高興的請它隆重登場。請大家拭目以待!
升級
就長期的升級來說,盡管React 16只是包括了一些有意義的內部改變,這個版本和其他主要的React版本仍可平分秋色。在今年早期的時候,新版版已服務于React和Messenger.com,然后我們通過發布一些beta版本和候選版本來解決增加的問題。除少數例外,如果你的項目使用v15.6版本沒有任何警示,那么可以升級到v16來服務項目了。
棄用
Hydrating一個服務端渲染的容器現在有了一個明確的API,如果你要進行服務端渲染,請使用ReactDOM.hydrate方法替換ReactDOM.render,客戶端的渲染請保持使用ReactDOM.render方法。
突破性的變化
- React 15有局限,使用未被文檔化的unstabel_handleError來支持error boundaries。在新版本中,這個方法被命名為了componentDidCatch。你可以使用codemod將項目自動遷移到新的API上。
- 如果ReactDOM.render和ReactDOM.unstable_renderIntoContainer在生命周期方法中被調用,則返回null。為了解決這個問題,你可以使用portals或者refs
- setState:
- setState參數為null的情況下不會再觸發更新。這允許你決定一個更新方法如果你想重新渲染。
- 在render方法中使用setState會觸發更新。這在之前是不被允許的,但是現在嗎,我們仍然建議不要在render中觸發setState。
- setState函數的回調(第二個參數)會在ComponentDidMount/componentWillUnmount方法會立即被觸發,而不是等所有組件重新渲染后再觸發。
- 當使用組件替代時,B.componentDidMount現在一定會出現在A.componentDidUnmount之前。而在之前,A.componentDidUnmount只會在某些情況下首先發生。
- 之前,當改變一個組件的ref時,ref和dom會在組件的render方法被調用之前分離?,F在,我們延遲了ref的改變,直到dom元素被改變了,ref才會和dom分離。
- 對于不使用React而是使用其他方法來重新渲染容器是不安全的。這在以前的版本中也許會生效,但是我們覺得不支持這樣做?,F在對于這種情況我們會發出一個警告,你需要使用ReactDOM.unmountComponentAtNode來清空你的節點樹。看這個栗子
- componentDidUpdate生命周期不再接受prevContext參數。
- shallow render不再調用componentDidUpdate()因為DOM refs不再有效。
- shallow renderer不再實現unstable_batchedUpdates()。
打包
- 不再有react/lib/* 和 react-dom/lib/*。即使在CommonJS環境下,React和ReactDOM都會預編譯成單獨的文件("flat bundles")。如果你的項目之前依賴于沒有文檔化的React內部方法,但是現在它們不再有效,聯系我們讓我們知道你的特殊栗子,我們會盡量提出一個可融合方案。
- 不再構建react-with-addons.js。所有兼容的插件都會發布到npm上,如果你需要我們也提供了瀏覽器單文件版本。
- 在15.x中啟用部分的介紹已經在核心包中被去掉了。如下的這些方法是等效的, React.createClas <=> create-react-class,React.ProprTypes <=> prop-types,React.DOM <=> react-dom-factories, react-addons-test-utils <=> react-dom/test-utils,shallow renderer <=> react-test-renderer/shallow??梢圆榭?5.5.0及15.6.0版本的博客以了解融合代碼及自動化codemods。
- 瀏覽器單文件版本構建文件的名字和路徑的改變是為了強調開發和生產環境的不同。如下所示:
- react/dist/react.js -> react/umd/react.development.js
- react/dist/react.min.js -> react/umd/react.production.min.js
- react-dom/dist/react-dom.js -> react-dom/umd/react-dom.development.js
- react-dom/dist/react-dom.min.js -> react-dom/umd/react-dom.production.min.js
( Over... )
轉自大轉轉FE,有改動
另,在知乎上有司徒正美大神的一篇不錯的文章:React16新特征總覽