很多等待已久的特性:
包括: 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可以避免阻塞主线程。