模版支持fragment
和string
类型,对应ReactElement数组和字符串
v16.2.0还提供了JSX的fragment支持:<></>
组件级错误处理,支持捕获子组件树内部异常,UI层的兜底方案
允许组件树与DOM树结构不一致,用于hovercards,tooltips等场景
例如tooltip在DOM结构上target与tip一般是兄弟关系(布局需要),而逻辑上tip是属于target的,是父子关系,portals特性用来处理这种场景
特殊的,事件冒泡经过处理,portals组件的父组件仍然能接到冒泡通知(React 16之前就内置了用来抹平DOM事件冒泡差异的事件系统,这里顺便支持拐弯冒泡 示例)
之前内置了HTML/SVG属性名白名单,自定义属性会被拦截并忽略掉,React 16去掉了这个限制
去掉该限制有2个原因,其一,这层内置的属性过滤对于非标准的(比如proposal阶段的)新属性和其它库/框架(比如Angular、Polymer)很不友好;其二,bundle里要内置一份体积不小的属性白名单,维护起来还挺麻烦
号称比React 15快3倍(benchmark场景,某业务场景据说1.3倍),做了几件事:
process.env
(在node环境访问这个变量很耗时)访问注意:React 16貌似也存在一些DOM node复用的问题:
However, it’s dangerous to have missing nodes on the server render as this might cause sibling nodes to be created with incorrect attributes.
P.S.具体要注意哪些危险场景,官方后面可能会给出专门的博客,暂时没有说清楚
React bundle瘦身(重构,扁平化打包策略,并换用rollup),体积小了30%
变化最大的应该是SSR,这次认真实现了一下(之前的SSR像是地上捡的)
server侧新增了renderToNodeStream, renderToStaticNodeStream
分别对应renderToString, renderToStaticMarkup
client侧新增了hydrate
client侧校验没那么严格了:
另外,还去掉了Server HTML结构上的checksum(data-react-checksum
)以及id(data-reactid
),响应体大小会降低不少:
<!-- react 15 -->
<div data-reactroot="" data-reactid="1"
data-react-checksum="122239856">
<!-- react-text: 2 -->This is some <!-- /react-text -->
<span data-reactid="3">server-generated</span>
<!-- react-text: 4--> <!-- /react-text -->
<span data-reactid="5">HTML.</span>
</div><!-- react 16 -->
<div data-reactroot="">
This is some <span>server-generated</span> <span>HTML.</span>
</div>
默认去掉了多余的process.env.NODE_ENV
访问,不需要手动编译去掉
SSR不再创建一次性的virtual DOM,整个快了不少
支持stream,带来的性能优势如下:
React 16 SSR不支持Error Boundary和Portal
服务端子组件渲染出错,不会被Error Boundary拦住。为了stream性能优势,牺牲了Error Boundary:
This is intentional / a known limitation. With streaming rendering it’s impossible to “call back” markup that has already been sent, and we opted to keep renderToString and renderToNodeStream’s output identical.
不仅renderToNodeStream, renderToStaticNodeStream
不支持Error Boundary,renderToString
也不支持,如上面说的,为了保持输出结果一致,没有维护2套机制
P.S.关于SSR Error Boundary的更多信息,请查看componentDidCatch doesn’t work in React 16’s renderToString
而Portal特性可能造成“回流”,与Error Boundary是一个道理,在stream机制下无法支持(想要往已经发送出去的stream里插入Portal内容,当然不可能)
全新的核心架构,(花了2年)整个重写了组件渲染机制,最关键的特性是异步渲染(async rendering),实现了可调度渲染(彻底解决mount流程一旦开始就无法中断的问题)
这样庞大的一个东西,伤筋动骨的重构执行过程很有意思。简单地说:
useFiber
特性开关切换,说是为了简化日常维护/冲突处理等tests-failing.txt, tests-passing.txt
添加到git追踪)、持续的生产环境验证(所谓dogfooding,从早期到最后单测通过的整个过程都在不断地进行“实战”验证,算是一种看得见的信念)P.S.具体重构过程见React 16: A look inside an API-compatible rewrite of our frontend UI library
所以暂时不支持异步渲染:
This initial React 16.0 release is mostly focused on compatibility with existing apps. It does not enable asynchronous rendering yet. We will introduce an opt-in to the async mode later during React 16.x. We don’t expect React 16.0 to make your apps significantly faster or slower, but we’d love to know if you see improvements or regressions.
render
返回多组件等之前不太容易实现的特性,重构之后都可以造出来了