DOM的diffing算法

Diff算法原理

根据新旧虚拟DOM的比较:

  1. 旧虚拟DOM中找到了与新虚拟DOM相同的位置的相同标签;
  • 若虚拟DOM中内容没变,直接使用之前的真实DOM
  • 若虚拟DOM中内容变了,则生成新的真实DOM随后替换掉页面中之前的真实DOM。
  1. 旧虚拟DOM中未找到与新虚拟DOM相同的位置的相同标签
    创建新的真实DOM,随后渲染到到页面。
<!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>Document</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 = {
      
      date: new Date()}
            componentDidMount(){
      
      
                setInterval(()=>{
      
      
                    this.setState({
      
      
                        date: new Date()
                    })
                },1000)
            }

            render(){
      
      
                return(
                    <div>
                        <h1>hello</h1>
                        <input type="text"/>
                        <span>现在是:{
      
      this.state.date.toTimeString()}</span>
                    </div>
                )
            }
        }
        ReactDOM.render(<Time/>,document.getElementById('test'))
    </script>
    <!-- 小结:
        1. diff算法是根据虚拟dom来对比更新后的内容和更新前的内容的差距
        2. diff算法的最小粒度是一个标签
         -->

    
</body>
</html>

Diff算法过程:
在这里插入图片描述

注意

  • DOM的diffing算法最小的粒度是标签
  • DOM的diffing算法对比的是很多层,逐层对比。

Diffing算法key的作用

案例: 展示列表

<!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>Document</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 Person extends React.Component{
      
      
            state = {
      
      
                persons:[
                    {
      
      id:1,name:'yang',age:19},
                    {
      
      id:2,name:'cheng',age:20},
                    {
      
      id:3,name:'wang',age:19}
                ]
            }
            add = ()=>{
      
      
                const {
      
      persons} = this.state
                const p ={
      
       id:persons.length+1, name:'小王', age: 20}
                this.setState({
      
      persons:[p, ...persons]})
            }
            render(){
      
      
                return(
                <div>
                    <h2>展示人员信息</h2>
                    <button onClick = {
      
      this.add}>添加一个小王</button>
                    <ul>
                        {
      
      
                            this.state.persons.map((person,index)=>{
      
      
                                return <li key={
      
      index}>{
      
      person.name}---{
      
      person.age}</li>
                            })
                        }
                    </ul>
                </div>
                )
            }
        }
        ReactDOM.render(<Person/>,document.getElementById('test'))
    </script>   
    <!-- 和vue一样 -->
</body>
</html>

在这里插入图片描述

虚拟DOM中key的作用:

  1. 简单地说key是虚拟DOM的标识,在diffing算法中时key起着非常重要的作用
  2. 详细的说: 当状态中的数据发生变化时,react会根据新数据形成新的虚拟DOM,然后进行新虚拟DOM与旧虚拟DOM的diffing比较,规则如下:
    1) 旧虚拟DOM中找到了与新虚拟DOM相同的key
  • 若虚拟DOM中内容没变,直接使用之前的真实DOM
  • 若虚拟DOM中内容变了,则生成新的真实DOM随后替换掉页面中之前的真实DOM。
    2) 旧虚拟DOM中未找到与新虚拟DOM相同的key
  • 创建新的真实DOM,随后渲染到到页面。

上述代码的diff算法(key时index)
在这里插入图片描述
但是如果使用id值作为key,就不会有如上效率问题,可以实现真实DOM的复用
在这里插入图片描述
而且如果页面中有输入的节点,如果key使用的是index,输入框的内容就会出现错乱。
在这里插入图片描述

小结

使用index作为key可能会引发问题

  • 若对数据进行了逆序添加、逆序删除等破坏顺序的操作就会产生没有必要的真实DOM更新,造成效率的浪费
  • 如果结构中还包含输入类的DOM,在列表前面添加数据的时候就hi产生错误的位置

猜你喜欢

转载自blog.csdn.net/mantou_riji/article/details/127334905