2

如果有状态的反应组件当时在 VDOM中C的位置PVT

然后

重新渲染后C,VDOM 会在V'哪里?T+1

例如,在这个true小提琴中,当父道具从变为时,第一个有状态组件的状态被“转移”到第二个有状态组件false。切换回来时,第二个组件的状态也会丢失。这怎么解释?记录这种行为的规则是否在某处可用?这里描述的不是很准确。

4

1 回答 1

1

你有一个像这样呈现的视图。

<MyComponent />

现在,如果要多次重新渲染此视图(导致相同的 state/lifecycle,或者您所说的转移,这不是我在每次渲染之间使用的词),那么以下条件是真的。

  • <MyComponent />此渲染树中的组件类型(标签名称:)是否与最后一个相同?
  • 组件是否与上次在同一个地方,相同的父级等?
  • 如果组件在上次渲染中分配了一个键属性,那么它是否在与上次相同的父级下的下一个渲染树中,具有相同的键值?

在下面的伪代码中想象一个完整的渲染树:

<div id="awesome-container">
    <Parent>
        { randomBoolean ? <AlphaChild /> : <BetaChild /> }
    </Parent>
</div>

Alpha 和 Beta 组件在被另一个组件替换时总是会卸载,并且它们的状态将是“重置”,也就是它们将作为新组件安装。

看上面的例子,你可能会认为这一切都是“未解析的 HTML”。自定义标签不是 DOM 中的最终产品。相反,解决后,它看起来更像这样:

<div id="awesome-container"> // just an element, is stateless
    <div class="parent"> // has a lifecycle/state tied to it
         <span name="alpha"> // also has a lifecycle/state
             <p>My job is to show the time: 10:00 AM</p>
         </span>
    </div>
</div>

如果AlphaChild突然被替换为BetaChild,那么保持AlphaChild状态/生命周期就没有意义了,对吧?如果我们确实想保留它,我们可能会保留一些对于列表中的单纯子级来说太重要的数据来维护(想到一个智能组件/父级或 Redux)。您总是可以使用 CSS 隐藏组件,只是为了保留状态。

如果我们没有钥匙,我们将无法切换组件。

constructor() {
this.state = { components: [ <AlphaChild />, <BetaChild />, <CharlieChild /> ] };
}

someEvent() {
    // Moves the first element in the array to the last position.
    this.setState({ 
        this.state.components: [this.components.slice(1)].push(this.state.components[0]))
    }
}

render() {
    { this.state.components }
}

无论上述组件的顺序如何,例如:

<BetaChild /> // has state
<AlphaChild /> // has state
<CharlieChild /> // has state

在组件的每次重新排序之间,状态将被终止。

<AlphaChild /> // has completely new state
<CharlieChild /> // has completely new state
<BetaChild /> // has completely new state

这就是为什么键在反应中非常重要的原因,将状态保持在一个很可能被重新排序的列表中。

没有比这更多的东西要跟踪了。如果一个组件从其父级中移除并出现在代码中的其他位置,它将不会保持其旧状态/生命周期,因为它们是相同的远非显而易见。事实上,没有任何合乎逻辑的方式可以告诉我们情况是这样的。甚至没有键,因为键可以是渲染过程中任何多个列表的一部分。

我希望这能让事情更清楚一点。如果您想了解有关虚拟 DOM 的更多信息,我建议您查看github 上的 Snabbdom。他们不会为您保留组件生命周期,因此您需要自己弄清楚。Snabbmitt可能有助于激发灵感。

不过一般来说,我认为您无需费心阅读有关虚拟 DOM 的太多内容,只要遵循原则就可以了。

于 2017-06-02T20:11:19.430 回答