由于现在存在相当多的问题,如果不对内部做一些大手术,有些问题很难甚至无法解决。所以他们希望能够撤销过去犯下的一些错误,这些错误导致了无穷无尽的后续修复和大量的技术债务。他们还希望删除事件系统中的一些抽象,这些抽象从 React 诞生之日起就几乎没有被动过,它们也是造成复杂性和臃肿的库文件的罪恶之源。这个行动称为“React Fire”。
React Fire 的具体规划
React 团队可能会在当前的计划中添加或删除一些内容,但总体是这样考虑的:
-
停止在 value 属性上反映输入值。这个特性最初是在 React 15.2.0 中添加的。这是一个非常普遍的需求,因为人们对 DOM 模型的理解就是在 DOM 检查器中看到的 value 应该与值 JSX 的 value 属性相匹配。但 DOM 其实不是这样的,在输入字段时,浏览器并不会更新 value 属性,所以 React 也不应该这样做。事实证明,这个变化虽然可能对依赖 CSS 选择器的一些代码有点用处,但却导致了一系列错误——其中一些仍未得到修复。从这一点上说,显然不值得继续与浏览器作斗争,所以应该回退。
-
将事件附加到 React root,而不是 document。在将 React 应用程序嵌入到更大的系统时,将事件处理器附加到 document 会成为一个问题。Atom 编辑器是最早遇到这种情况的案例之一。大型网站通常会出现非常复杂的边缘案例,通过 stopPropagation 与非 React 代码发生交互或进行跨 React root 交互。他们还希望能够尽早将事件附加到每个 root,这样就可以在更新期间减少运行时检查。
-
从 onChange 切换到 onInput,并且不需要为不受控组件进行 polyfill。React 在 DOM 中使用了一个不同的事件名来表示 input 事件,这无疑让人感到有些困惑。虽然通常应该避免在没有得到显著好处的情况下做出这样的大变更,但我们还是希望能够因此消除一些复杂性。因此,将这两个变更结合在一起是有意义的,并借此机会让 onInput 和 onChange 与 DOM 事件在不受控组件上的行为保持一致。
-
大幅简化事件系统。当前的事件系统自 2013 年初始实现以来,几乎没有发生任何变化。它在 React DOM 和 React Native 中被重复使用,因此它没有必要是抽象的。它提供的很多 polyfill 对于现代浏览器来说是不必要的,并且其中一些产生的问题比它们解决的问题还要多。它也占了 React DOM 包大小的很大一部分。Dan 表示,现在还没有非常具体的计划,但有可能会完全将事件系统 fork 出去。完全摆脱合成事件似乎是合理的,我们应该停止使用冒泡事件(比如媒体事件,它们不会在 DOM 中冒泡,而且也没有充分的理由进行冒泡)。React 团队希望保留一些特定于 React 的功能,例如跨门户的冒泡,但他们将尝试通过更简单的方法(例如重新分配事件)来实现。
-
className 改为 class。这个提案已经被提了无数次了。在 React 16 中, 允许将 class 传给 DOM 节点。但避免语法限制所带来的好处无法抵消它所造成的混乱,他们不会单独做出这个变更,需要与上述的结合在一起才有意义。不能在没有给出警告的前提下让二者同时存在,因为组件生态系统很难处理好它们。每个组件都需要学会如何正确处理它们,还要冒着出现冲突的风险。
权衡利弊
Dan 表示,如果继续为 React Native Web 等项目公开当前的私有 React 事件系统 API,他们就无法做出这些变更。不过,React Native Web 需要一个不同的策略,因为 React Fabric 可能会将更多的响应者系统移到 Native 端。
所以,React 团队可能需要放弃与某些旧版浏览器的兼容性,或者需要提供更多独立的 polyfill。不过,他们仍希望能够支持 IE11,但可能不会试图消除现有浏览器的一些差异——这也是很多现代 UI 库所采取的立场。
未来计划
在这个阶段,这个项目非常具有探索性。他们不确定上述的所有事情是否能够奏效。他们会在 Facebook 内部进行实验,并以渐进的方式逐步实现。可能还需要引入一个功能标志,fork 出一些代码,并让 Facebook 的一小部分人先试用新功能。16.x 开源版本将保留旧有的行为,但在 master 上,可以通过功能标志开启新功能。
查看英文原文: https://github.com/facebook/react/issues/13525
感谢覃云对本文的审校。
评论