React 学习笔记(16)Diff算法

175 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

验证Diff算法

从现在开始直接使用React17.0.1版本

diff算法,是React用来计算出虚拟 DOM中真正变化的部分,并只针对该部分进行原生DOM操作,而非重新渲染整个页面,从而提高了页面渲染效率。同样在Vue中也有一样算法。

从一个例子中这展示这个diff算法:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>学习React</title>
</head>

<body>
    <div id="test"></div>

    <script type="text/javascript" src="../js/17.0.1/react.development.js"></script>
    <script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/17.0.1/babel.min.js"></script>
    <script type="text/babel">
        class Time extends React.Component {
            state = { data: new Date() }

            componentDidMount() {
                setInterval(() => {
                    this.setState({
                        data: new Date()
                    })
                }, 1000)
            }
            render() {
                return (
                    <div>
                        <h1>hello</h1>
                        <span>现在是:{this.state.data.toTimeString()}</span>
                    </div>
                )
            }
        }

        ReactDOM.render(<Time />, document.getElementById('test'))
    </script>
</body>

</html>

效果:

22.gif 可以说React无时无刻都在用到这个diff算法,上面的例子使用了了一个一秒钟刷新一次的定时器不停地在更新这个span标签,是最简单的例子。

Diff算法

主要有三个层级遍历:

  • 1.tree层级 DOM树依次遍历所有DOM树节点,跨层级的操作不做优化,只会对相同层级的节点进行比较。React 进行了优化只有删除、创建操作,没有移动操作。

  • 2.conponent 层级 按照React组件树依次从顶向下遍历,只有删除和创建。

  • 3.element 层级 对于比较同一层级的节点每个节点在对应的层级用唯一的key作为标识进行对比,除了进行删除创建还有移动操作。 统计同级节点的key进行对比,位置不同,内容相同就进行移动,这里非常细节。如果当前节点在新集合中的位置比老集合中的位置靠前的话,是不会影响后续节点操作的,这里这时候被动字节不用动

由于dom节点的移动操作开销是比较大的,没有key的情况下要比有key的性能更好,在渲染很多同级元素的时候,元素key属性的作用是用于判断元素是新创建的还是被移动的元素,从而减少不必要的元素渲染,因此key需要为每一个元素赋予一个确定的标识。

React 判断Key的流程:

graph TD
组件或元素 --> 判断是否存在Key值
判断是否存在Key值 -->不存在
判断是否存在Key值 -->存在
不存在 -->采用Diff算法比较
存在-->key值是否一致
key值是否一致-->不一致
key值是否一致-->一致
不一致 --> 组件进行销毁或新建
一致 --> 属性是否发生变化
属性是否发生变化-->是
属性是否发生变化-->否
是-->更新
否-->不需要改变