React 17 带来了什么?
他来了,他来了,他来了,当我们还在为 Vue next 头秃的时候,React 17 也正朝我们阔步走来!
但是!不要慌!React 17 带来了 “没有新特性” !是不是重燃了对生活的斗志!稳住,我们能赢!!!
言归正传,那么 React 17 的意义是什么呢? “垫脚石”
逐步升级
在以前,React 一直遵循着 “all-or-nothing” 的升级策略。你可以继续使用旧版本,也可以将整个应用程序升级至新版本。但没有介于两者之间的情况。这个策略有很多局限性:
- 许多 API 的变更,并不能以自动化的方式来完成。
- 至今可能大多数应用程序从未使用过它们,但 React 仍然需要支持它们。
React 17 的出现,可以让我们逐步升级应用程序。这意味着当 React 18 或未来版本问世时,我们不仅可以选择一次升级整个应用程序,也可以选择逐步升级。
React 17 做了些什么?
为什么不能在一个系统中嵌套使用不同版本的 React?
主要是因为 React 的事件系统 SyntheticEvent 。React 对浏览器的原生事件进行了一层包装,这样可以抹平不同浏览器之间的兼容性差异,同时它也拥有和浏览器原生事件相同的接口,包括:stopPropagation() 和 preventDefault();另一方面可以做更多优化:例如利用事件委托机制,大多数事件的触发都代理到了 document,而不是 DOM 节点本身,简化了 DOM 事件处理逻辑,减少内存开销。
所以如果页面上有多个 React 版本,它们都将在顶部注册事件处理程序,这会中断 e.stopPropagation() ,如果嵌套树停止了事件的传播,则外部树仍将接收该事件,这使得难以嵌套不同版本的React。
import React, { Component } from "react";
export default class App extends Component {
click = (item) => {
console.info(item);
};
handleClick = () => {
console.info("点击了");
};
render() {
const data = [1, 2, 3, 4, 5];
return (
<div>
<button onClick={this.handleClick}>点击</button>
<ul>
{data.map((item) => {
return (
<li
key={item}
style={{
marginBottom: "16px",
width: "200px",
height: "50px",
background: "#2196F3",
color: "#fff",
}}
onClick={() => this.click(item)}
>
{item}
</li>
);
})}
</ul>
</div>
);
}
}
在 React v16 的环境中执行以上代码,在控制台输出如下:
在 React v17 的环境输入如下:
更改事件委托
为了实现逐步升级, React 对事件系统进行了一些更改,而这些更改可能会对代码产生影响,这也是 React 17 成为主要版本的原因。实际上,10 万个以上的组件中受影响的组件不超过 20 个,因此,大多数应用程序升级到 React 17,不会产生太多影响。
React 17 将事件处理器附加到渲染 React 树的根 DOM 容器,从
document.addEventListener() 变为 rootNode.addEventListener()
。这不会影响根 DOM 容器之外的 Portals。React 还会监听 portals 容器上的事件。
如果模块中使用 document.addEventListener(...) 手动添加了 document 监听,你可能希望能捕获到所有 React 事件。在 React 16 或更早版本中,即使你在 React 事件处理器中调用 e.stopPropagation(),你创建的 document 监听仍会触发,这是因为原生事件已经处于 document 级别。使用 React 17 冒泡将被阻止(按需),因此你的 document 级别的事件监听不会触发。
其他重大变化
主要有以下几方面,由于大多是偏底层的,这里就不赘述了,感兴趣的小伙伴可以去官网查阅。
- 对标浏览器
- 去除事件池
- 副作用清理时间
- 返回一致的 undefined 错误
- 原生组件栈
- 移除私有导出
全新的 JSX 转换
只是 JSX 编译的结果发生了变化,JSX 的语法并没有发生变化。
改变后有如下优点:
- 使用全新的转换,可以单独使用 JSX 而无需引入 React。
- 根据配置,JSX 的编译输出可能会略微改善 bundle 的大小。
- 减少学习成本。
总结
React 17 的版本的出现改变了 “all-or-nothing” 的现状,能够让我们在日后平滑的升级到新的版本。