虚拟 DOM 和 DOM diff

125 阅读2分钟

虚拟DOM

优点: 减少DOM操作,虚拟DOM 可以将多次操作合并为一次操作,比如添加1000个节点,却是一个接一个操作的(减少频率) 虚拟DOM借助 DOM diff 可以把多余的操作声调,比如你操作1000个节点,其实只有10个新增的.

跨平台: 虚拟DOM 不仅可以变成DOM,还可以变成小程序、ISO应用、安卓应用、因为虚拟DOM本质上只是一个JS对象

缺点: 需要额外的创建函数。如createElement或 h, 但是可以通过JSX 来简写成 XML

// 如何创建虚拟DOM
Vue Template

<div class="red" @click="fn">
    <span>string1</span>
    <span>string2</span>
</div>
// 通过 vue-loader 转为 h形式

const vNode = {
    tag: 'div' // 标签名 or 组件名
    data:{
        class: 'red',  //标签上的属性
        on: {
            click: ()=>{} // 事件
        }
    },
    childred:[ // 子元素
        {tag: 'span','....'}
        {tag: 'span','....'}
    ]
}

// vue 只能在render 函数里获取得到h
h('div',{
    class: 'red',
    on:{
        cilck: ()=>{}
    }
})
// React
const vNode ={
    key:null,
    props:{
        childred: [//子元素
            {type:'span',...},
            {type:'span',...}
        ],
        className: 'red', // 标签上的属性
        onclick: ()=>{} // 事件
    },
   ref:null,
   type: 'div' // 标签名 or 组件名
}

<div className="red" onclick="()=>{}">
    <span>span1</span>
    <span>span2</span>
</div>
通过 babel 转为createElement 形式

createElement('div',{
    className:'red',
},
[
    createElement('span',{},'span1'),
    createElement('span',{},'span2')
])

DOM diff

什么是 DOM diff 就是一个函数,我们成为 patch.

patches = patch(oldVNode,newVNode)

patches就是要运行的DOM 操作。

DOM diff 大概逻辑是

将新旧两棵树进行逐层对比,找出哪些节点需要更新,如果节点是组件,就看Component diff. 如果是组件就先看组件的类型,类型不同直接替换,删除旧的,类型相同就直接更新,然后在深入组件进行对比。 如果节点是原生标签,就看标签名,标签名不同直接替换,如果相同就看属性,属性相同就更新属性。

DOM diff 的优点 :

可以做到只把变化的部分重新渲染,提高渲染效率的过程。

DOM diff 的缺点

同级节点对比会存在BUG。

给每个节点起个名字 ID,ID 可以是数字,字符串,能代表它是谁即可

image.png

image.png

image.png