反应:在动画期间调用 Render()发生什么了?

问题描述

我想知道 React 如何处理在组件动画期间调用的 Render。在下面的例子中,一个组件被重新渲染

假设在组件动画期间组件状态发生了变化,因此组件被重新渲染。 React 会取代物理 DOM 还是会识别组件处于动画中? 这是我认为会发生的事情

步骤 1:组件安装 组件第一次挂载到物理DOM。组件的动画持续 60 秒。该组件有一个更改状态计时器,它将在 30 秒内关闭。同时,react 会在挂载时保存虚拟 DOM。

第 2 步:触发状态更改并重新渲染组件 30 秒后,父组件将发生状态更改,组件将重新渲染。此时组件处于动画中期,并使用 react-transition-group,将“className-active”css 类应用于子项。 React 现在将比较当前的虚拟 DOM 和旧的虚拟 DOM。虚拟 DOM 是不同的,因为孩子现在应用了活动类(而不是“输入”类)。结果,react 会将更新后的组件插入到物理 DOM 中(即使物理 DOM 不需要更新!)。因此,屏幕会闪烁...

这是描述上述场景的代码

import React from 'react'
import Csstransition from 'react-transition-group'
                                                                                                                                                                                                                     ```
class ExampleComponent extends React.Component {
      constructor(props) {
           super(props);
           this.state = {reRender : false};
           setTimeout(() => {this.setState({reRender: true})},30000) 
           /* 30,000 ms is 30 seconds. 
              Set state will fire in 30 seconds,and the parent component will 
             rerender itself and the     
           */
     }
      render()  {
          return (
                <Csstransition
            appear = {true}
            in = {true}
            classNames = 'test'
            timeout = {60000}>
                <span> test </span>
        </Csstransition>
          )

      }

}

这里是相关的css类

.test-appear,test-enter{
       opacity : 1;
}
.test-appear-active,.test-enter-active {
      opacity: 0; 
      transition: opacity; 
      transition-duration: 60000;
}
.test-appear-done,.test-enter-done {
      opacity: 0;    
}

给定这段代码,我想一步一步地了解 React 生命周期和虚拟 DOM 中发生的事情。物理 DOM 会在 30 秒后更新还是会反应识别它处于动画中期?虚拟 DOM 如何保存之前的状态?

解决方法

在这种情况下,CSSTransition 保持内部状态以了解它处于动画的哪个阶段。

React 不会重置 CSSTransition 实例的状态,因为它知道它引用了同一个元素(React 依赖于组件的类型和在树上的位置来决定它是否是同一个元素,或者定义时的 key 道具)

因为 CSSTransition 的内部状态是相同的,所以它的 render 方法在组件状态改变之前和之后呈现相同的 css 类。

看看你的例子,它没有闪烁https://codesandbox.io/s/hopeful-shaw-c9ldr

CSSTransition 可能会更改状态以响应您传递给它的任何道具的更改(在这种情况下甚至不会发生),但这取决于 CSSTransition 实现。>

最后,如果您将不同的 key 传递给 CSSTransition,它会重置动画,因为 React 会将其视为一个新组件,因此会卸载前一个并安装一个新组件,并使用新组件内部状态。

在此处查看动画重置示例: https://codesandbox.io/s/jolly-maxwell-2ihkf

,

React 不关心动画。它所关心的只是确保 DOM 根据 vDOM 中的变化进行更新。

当您从 DOM 中间动画中手动删除元素时,动画将停止。 React 将执行完全相同的操作,即对树进行的任何更改(不包括不改变树结构的 prop 更改)将在下一个渲染周期立即卸载并重新安装相关元素。

在你的情况下,由于树没有改变,它不会拆除任何元素。 render() 将被调用,react 将比较 vDOM 的旧版本和新版本,如果有任何更改,只会修改 props。但是您手动重新渲染状态更改不会以任何方式影响 vDOM

有关详细信息,请参阅 Reconciliation 文档。