zoukankan      html  css  js  c++  java
  • diff算法是如何比较的,保证让你看的明明白白的!

    更新dom节点,最小力度去跟新

    index.html
    <body>
        <h1>你好啊!</h1>
        <button id="btn">该变数据</button>
        <div id="container"></div>
    </body>
    <script src="xuni/bundle.js"></script>
    </html>
    
    index.js文件
    import {
      init,
      classModule,
      propsModule,
      styleModule,
      eventListenersModule,
      h,
    } from "snabbdom";
    
    let myVnode1 = h('ul', {}, [
      h('li', {}, '姓名'),
      h('li', {}, '年龄'),
      h('li', {}, '爱好'),
    ])
    // 使用init函数创建 patch函数 
    const patch = init([classModule, propsModule, styleModule, eventListenersModule])
    const container = document.getElementById('container')
    // 让虚拟节点上树
    patch(container, myVnode1)
    
    // 改变数据
    let myVnode2 = h('ul', {}, [
      h('li', {}, '姓名'),
      h('li', {}, '年龄'),
      h('li', {}, '爱好'),
      h('li', {}, '性别'),
    
    ])
    let btn = document.getElementById('btn')
    btn.onclick = function () {
      patch(myVnode1,myVnode2)
    }
    

    发现的现象

    当我手动去更改页面中的数据的时候。
    在点击按钮。我们发现只追加了性别。
    我更改的数据并没有跟新。
    说明diff是进行最小力度去跟新的
    

    那我们把数据添加在最前面会发生什么呢?

    let myVnode1 = h('ul', {}, [
      h('li', {}, '姓名'),
      h('li', {}, '年龄'),
      h('li', {}, '爱好'),
    ])
    // 使用init函数创建 patch函数 
    const patch = init([classModule, propsModule, styleModule, eventListenersModule])
    const container = document.getElementById('container')
    // 让虚拟节点上树
    patch(container, myVnode1)
    
    // 改变数据
    let myVnode2 = h('ul', {}, [
      //在最前面添加,发现跟刚才的比一样了?
      //他将我们更改的数据复原了?
      //这个时候又小伙伴会说,diff不是最小粒度去更新了
      h('li', {}, '性别'),
      h('li', {}, '姓名'),
      h('li', {}, '年龄'),
      h('li', {}, '爱好'),
    ])
    let btn = document.getElementById('btn')
    btn.onclick = function () {
      patch(myVnode1,myVnode2)
    }
    

    diff不是最小粒度跟新?

    在最前面添加,发现跟刚才的比一样了?
    他将我们更改的数据复原了?
    这个时候又小伙伴会说,diff不是最小粒度去更新了?
    其实diff一直都是最小力度跟新,是你忘记增加key值了。
    我们加上key值看看呢??
    

    添加key值后

    let myVnode1 = h('ul', {}, [
      h('li', {key:'001'}, '姓名'),
      h('li', {key:'002'}, '年龄'),
      h('li', {key:'003'}, '爱好'),
    ])
    // 使用init函数创建 patch函数 
    const patch = init([classModule, propsModule, styleModule, eventListenersModule])
    const container = document.getElementById('container')
    // 让虚拟节点上树
    patch(container, myVnode1)
    
    // 改变数据
    let myVnode2 = h('ul', {}, [
      h('li', {key:'00x'}, '性别'),
      h('li', {key:'001'}, '姓名'),
      h('li', {key:'002'}, '年龄'),
      h('li', {key:'003'}, '爱好'),
    ])
    let btn = document.getElementById('btn')
    btn.onclick = function () {
      patch(myVnode1,myVnode2)
    }
    

    添加key值顶级节点类型改变的情况

    当我们添加key值后,发现数据果然是最小力度去更新的,对吧!
    如果将ul更改为div,还是最小力度跟新吗?
    
    let myVnode1 = h('ul', {}, [
      h('li', {key:'001'}, '姓名'),
      h('li', {key:'002'}, '年龄'),
      h('li', {key:'003'}, '爱好'),
    ])
    // 使用init函数创建 patch函数 
    const patch = init([classModule, propsModule, styleModule, eventListenersModule])
    const container = document.getElementById('container')
    // 让虚拟节点上树
    patch(container, myVnode1)
    
    // 改变数据
    let myVnode2 = h('div', {}, [
      h('li', {key:'001'}, '姓名'),
      h('li', {key:'002'}, '年龄'),
      h('li', {key:'003'}, '爱好'),
    ])
    let btn = document.getElementById('btn')
    btn.onclick = function () {
      patch(myVnode1,myVnode2)
    }
    
    这个时候我们增加上key值了,按照之前的操作。
    发现一个问题。数据全部恢复最初始值了。
    
    在采取diff算法比较:新旧节点进行比较,
    比较只会在同层级进行, 不会跨层级比较。
    
    如果两个节点都是一样的,那么就深入检查他们的子节点。
    果两个节点不一样那就说明 Vnode 完全被改变了(ul和div节点不一样),
    就可以直接使用新节点替换老节点。【他们的子代不会进行比较了】 
    
    虽然这两个节点不一样但是他们的子节点一样怎么办?
    别忘了,diff可是逐层比较的,
    如果[第一层不一样那么就不会继续深入比较第二层了。
    (我在想这算是一个缺点吗?相同子节点不能重复利用了??...)
    
    这个时候你可能会说:这个diff算法也不会那么牛逼呢!
    并不是最优的。
    【虽然这两个节点不一样但是他们的子节点一样怎么办?】
    在我们工作中:其实这指一种非常合理的机制。
    我们几乎并不会出现这样的情况
    <ul v-if="falg">
        <li v-for="item,index" in list>{{item }}</li>
    </ul>
    
    <ol v-if="falg">
        <li v-for="item,index" in list>{{item }}</li>
    </ol>
    这样的代码在我们工作中几乎是不会出现的呢?
    
    什么叫做不会跨层比较?
    <div>
        <p>123123 </p>
    </div>
    与
    <div>
       <h2> <p>123123 </p> </h2>
    </div>
    
    div与div比较
    p与h2比较
    当p与h2比较的时候,他们他们节点不一样,直接使用替换。
    此时并不会在使用diff了
    

    遇见问题,这是你成长的机会,如果你能够解决,这就是收获。

    作者:明月人倚楼
    出处:https://www.cnblogs.com/IwishIcould/

    想问问题,打赏了卑微的博主,求求你备注一下的扣扣或者微信;这样我好联系你;(っ•̀ω•́)っ✎⁾⁾!

    如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,或者关注博主,在此感谢!

    万水千山总是情,打赏5毛买辣条行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主(っ•̀ω•́)っ✎⁾⁾!

    想问问题,打赏了卑微的博主,求求你备注一下的扣扣或者微信;这样我好联系你;(っ•̀ω•́)っ✎⁾⁾!

    支付宝
    微信
    本文版权归作者所有,欢迎转载,未经作者同意须保留此段声明,在文章页面明显位置给出原文连接
    如果文中有什么错误,欢迎指出。以免更多的人被误导。
  • 相关阅读:
    MFC中CTREECTRL的checkbox问题
    GLOG的使用说明
    安装Electron
    WIN32中DLL的建立
    MFC动态创建菜单
    C++迭代器
    VIM常用命令
    层次遍历二叉树
    sql存储过程中加引号
    Apache Tomcat 绿色版安装Service(服务)
  • 原文地址:https://www.cnblogs.com/IwishIcould/p/15685352.html
Copyright © 2011-2022 走看看