React如何知道组件是从DOM中删除的?

时间:2017-07-09 13:29:54

标签: javascript reactjs dom

在React官方Facebook文档的Adding Lifecycle Methods to a Class下,提到:

  

5)如果从DOM中删除了Clock组件,React会调用componentWillUnmount()生命周期钩子,以便停止计时器。

只是想了解如何?我知道React知道什么时候要在DOM中插入组件,所以它可以调用componentDidMount生命周期钩子。

但对于componentWillUnmount,它只是说永远 DOM 中删除了。似乎表明它是真正的DOM而不是React DOM。也许可以用javaScript / jQuery删除组件,componentWillUnmount应该触发。

React究竟知道该组件已从真正的DOM中删除了吗?可能有观察者吗?

由于

2 个答案:

答案 0 :(得分:6)

实际DOM上没有观察者。 每次调用组件的render函数时,都会重新构建Virtual DOM。如果不再需要某个组件,则会从虚拟DOM中删除该组件。

差异算法将实际DOM中需要更改的部分标识为实际DOM,以反映虚拟DOM:某些组件必须添加到实际DOM(=称为安装),其他组件必须删除(=卸载)。整个过程称为reconciliation

正是由于此协调过程,React 知道要从实际DOM中删除哪些组件。在删除组件之前,React调用componentWillUnmount()生命周期钩子。

如果另一个脚本(Javascript或jQuery)导致从实际DOM中删除某个组件,React将永远不会注意到它,因此不会调用componentWillUnmount()生命周期钩子。

答案 1 :(得分:3)

事实并非如此。如果您手动从DOM中删除组件,它将不会触发componentWillUnmount .. 只有当组件不再存在时,它才会通过Virtual DOM发生:

// Unmount children that are no longer present.
for (name in prevChildren) {
  if (
    prevChildren.hasOwnProperty(name) &&
    !(nextChildren && nextChildren.hasOwnProperty(name))
  ) {
    prevChild = prevChildren[name];
    removedNodes[name] = ReactReconciler.getHostNode(prevChild);
    ReactReconciler.unmountComponent(
      prevChild,
      false /* safely */,
      false /* skipLifecycle */,
    );
  }
}
  

https://github.com/facebook/react/blob/5c6a496d98b80d19d851c2ec3a56d760b7118a50/src/renderers/shared/stack/reconciler/ReactChildReconciler.js

unmountComponent然后会致电componentWillUnmount

我通过打开devtools并删除了一些具有componentWillUnmount生命周期方法的组件来手动测试componentWillUnmount