zoukankan      html  css  js  c++  java
  • vDom和domDiff

    虚拟dom和domDiff

    1. 构建虚拟DOM
    var tree = el('div', {'id': 'container'}, [
        el('h1', {style: 'color: blue'}, ['simple virtal dom']),
        el('p', ['Hello, virtual-dom']),
        el('ul', [el('li')])
    ])
    
    2. 通过虚拟DOM构建真正的DOM
    var root = tree.render()
    document.body.appendChild(root)
    
    3. 当数据发生变化,生成新的虚拟DOM
    var newTree = el('div', {'id': 'container'}, [
        el('h1', {style: 'color: red'}, ['simple virtal dom']),
        el('p', ['Hello, virtual-dom']),
        el('ul', [el('li'), el('li')])
    ])
    
    4. 比较两棵虚拟DOM树的不同
    var patches = diff(tree, newTree)
    
    5. 在真正的DOM元素上应用变更
    patch(root, patches)
    

    难点就在于比较diff
    给你两个数组,数组里装着几个对象,对比这两个数组的区别,首先需要考虑的是什么,顺序,也就是复用性,因为dom里有子元素,如果能移动位置,就优先移动位置,对比之后,没有的就删了,在把新的添加就行,但是,但是对比对象的成本非常的高,我要对比两个对象是不是同一个要对比name,对比age,对比很多的值,才能知道这个是原本的第一个值现在变到第三个了,如何减少对比,用key,用对象里不变的量做对比,因为有key,所以对象级别的对比就变成了字符串数组级别的对比,这也是vue的优化方案之一,如何对比字符串数组的diff,往下看

    image.png

    // 列表对比,主要也是根据 key 值查找匹配项
    // 对比出新旧列表的新增/删除/移动
    function diffList(oldList, newList, index, pathchs) {
        let change = []
        let list = []
        const newKeys = getKey(newList)
        oldList.map(v => {
    	 if (newKeys.indexOf(v.key) > -1) {
    		 list.push(v.key)
    	 } else {
    		 list.push(null)
    	 }
        })
        // 标记删除
        for (let i = list.length - 1; i>= 0; i--) {
    	 if (!list[i]) {
    	    list.splice(i, 1)
    	    change.push({ type: 'remove', index: i })
    	 }
        }
        // 标记新增和移动
        newList.map((item, i) => {
    	 const key = item.key
    	 const index = list.indexOf(key)
    	 if (index === -1 || key == null) {
    		 // 新增
    		 change.push({ type: 'add', node: item, index: i })
    		 list.splice(i, 0, key)
    	 } else {
    		 // 移动
    		 if (index !== i) {
    			 change.push({
    				 type: 'move',
    				 form: index,
    				 to: i,
    			 })
    			 move(list, index, i)
    		 }
    	 }
        })
        return { change, list }
    }
    

    更新
    新增的新增,删除的删除的,移动的先移动,再对比移动的数据的标签值的变化,比如值的变化,class的变化,内容的变化等等,之后还要递归执行子一级的变化,才能完成一次domDiff

    理想化
    上面说的只是理想化的对比,如果我不设置key呢,vue会自己设置,就比如vue的dom上个特殊的id,那vue能自己设置还要我们设置干什么,他设置需要去生成uuid之类的id,是需要成本的

    参考资料
    domDiff第一篇
    domDiff第二篇
    domDiff第三篇
    domDiff第四篇
    domDiff第五篇
    domDiff第六篇
    domDiff第七篇

  • 相关阅读:
    Js时间处理
    Css 显示删除条目效果
    vue权限控制菜单显示的简单实现
    js取对象的属性值循环
    标题的内容响应式设计
    将一个字符串当做一个方法名或对象的key
    JSON序列化和解析
    import 与export详解
    使用flask-mail扩展发送邮件
    正则表达式练习-计算器实现
  • 原文地址:https://www.cnblogs.com/pengdt/p/12072473.html
Copyright © 2011-2022 走看看