#204·cyclejs

避免重新创建/评估 VDOM 子树

作者: josephsavona创建于 2016年1月28日更新于 2024年10月5日
标签priority 2 (could)issue is feature suggestionscope: dom

我正在阅读 Cycle 的实现,在尝试一些示例时注意到了一个意想不到的行为:似乎每当父组件发生变化时,组件都会重新创建,导致大量的反应式计算图被丢弃并更频繁地重新创建,这似乎比必要的更多。通过示例来更好地解释这个问题。### 示例: TodoMVC 1. 打开 Cycle todomvc 示例 应用程序示例。 2. 创建两个新的待办事项。 3. 断点 TodoItem 组件定义。 4. 对任何一个待办事项进行任何更改,并观察到所有 TodoItem 组件都被丢弃并从头重新渲染。 从概念上讲,在步骤 2 之后,反应值的图形看起来像这样: todo a -----\ todos ---> app todo b -----/ 根据我对文档的理解,如果只有待办事项 "a" 发生变化,则 TodoItem 不会为待办事项 "b" 重新计算,并且该图形的部分可以重用。 实际上,情况并非如此,两个组件都被重新创建并重新渲染(到虚拟 DOM)。我也预期添加一个新待办事项不会导致待办事项 "a" 和 "b" 被创建或重新渲染,但它们确实如此。 ### 一般化 更一般地说,这种问题似乎会出现在遵循文档模式构建应用程序的任何 Cycle 应用程序中。例如,在 组件文档 中,BMI 计算器的视图函数如下: JavaScript const vtree$ = Observable.combineLatest(sources.props$, value$, (props, value) => div('.labeled-slider', [ // ... abbreviated input('.slider', { type: 'range', min: props.min, max: props.max, value }) ])); 由于 input 立即调用函数并创建组件,似乎没有任何方法可以让应用程序在图形的同一位置重用之前的 input(除非在一侧进行一些缓存)。 ### 问题 这似乎是一个潜在的性能问题。如果 TodoItem 不是复杂组件 - 即具有大量(间接)子组件 - 则重新构建频繁地很昂贵。请注意,React 解决了这个问题,通过使用描述符 - React 中 input 调用的等价物 - 可以创建输入组件及其参数的描述,从而允许 React 根据 DOM 结构和 key 重用现有组件。虚拟 DOM 理论上支持这种相同的优化 - 它由底层的 virtual-dom 差异算法支持 - 但此逻辑仅存在于驱动程序中,该驱动程序被抽象化了,远离视图。并不立即清楚一个 Cycle 应用程序如何被改变,以充分利用 virtual-dom 的组件重用,从而避免重新创建组件,就像 React 那样…

内容来源: cyclejs/cyclejs