Vue学习笔记---Vue中的虚拟DOM以及它 的Diff算法

一、前言

  • Dom操作是比较浪费时间和性能的,当数据量很大的时候,更新DOM是很耗费性能的操作。Vue提供了虚拟DOM的解决办法。
  • Vue的核心是双向绑定和虚拟DOM(Virual DOMA),虚拟DOM是用js对象记录一个DOM节点的副本,当DOM发生更改的时候,先用虚拟DOM进行Diff,算出最小差异,然后再修改真实DOM。虚拟DOM和真实的DOM有一层映射关系,很多需要操作DOM的地方都会去操作虚拟DOM,最后统一更新DOM,因而可以提高性能。
  • 虚拟DOM的核心思想就是对复杂的文档DOM结构提供一种方便的工具,进行最小化的DOM操作,使得开发效率和执行效率得到了保证。

二、虚拟DOM的框架/工具操作流程

  1. 在内存中生成一棵虚拟DOM树
var data={
	arr:[]
}
var vDom = {
            tag:"div",
            attr:{
                id:"content"
            },
            children:[
                {tag:"p",content:2},
                {tag:"ul",attrs:{className:"list-group"}}
            ]
        }
  1. 根据内存中的虚拟DOM初始化渲染成真实DOM
  2. 当数据变化,或者说是页面需要重新渲染的时候,会重新生成一个新的完整的虚拟DOM
//修改data里面的数据
 data.arr.push("
  • 111111
  • "
    ) data.arr.push("
  • 222222
  • "
    ) var newDom = { tag:"div", attr:{ id:"content" }, children:[ {tag:"p",content:2}, {tag:"ul",attrs:{className:"list-group"},children:[ {tag:"li",content:"11111"}, {tag:"li",content:"22222"} ]} ] }
    1. 拿新的虚拟DOM来和旧的虚拟DOM做对比(使用diff算法)。
    2. 得到需要更新的地方之后,重新进行真实DOM结构的渲染
      在上述代码中,当数据发生变化的时候,大量操作的是虚拟DOM,而虚拟DOM属于内存数据,操作起来性能要高的多,而真实的DOM操作,只有在追加新数据的时候才会进行操作,这样大大提高了性能。

    三、虚拟DOM的Diff算法与key属性

    在虚拟DOM中,DOM的状态发生变化时,虚拟DOM会进行Diff运算,来更新只需要被替换的DOM,而不是全部重绘。
    在Diff算法中,只平层的比较前后两棵DOM树的节点,没有进行深度的遍历。

    1. 如果节点类型改变,直接将旧节点卸载,替换为新节点,旧节点包括下面的子节点都将被卸载,如果新节点和旧节点只是类型不同,但下面的所有子节点都一样,这样做的效率就不高。
    2. 节点类型不变,属性或者属性值改变,不会卸载节点,执行节点更新的操作。
    3. 文本改变,直接修改文字内容。
    4. 移动、增加、删除子节点时:

    Vue学习笔记---Vue中的虚拟DOM以及它 的Diff算法_第1张图片
    如果想在中间插入节点F,简单粗暴的做法就是:卸载C,装载F,卸载D,装载C,卸载E,装载D,装载E。(通俗的来说就是,我们在购买火车票的时候,有人插队在我们面前,我们只能往后退一个位置,依次占用后面买票者的位置。)如下图:
    Vue学习笔记---Vue中的虚拟DOM以及它 的Diff算法_第2张图片
    写代码时,如果没有给数组或者枚举类型定义一个key,就会采用上面的简单粗暴做法。
    如果给元素增加key后,Vue就能根据key,直接找到具体的位置进行操作,效率比较高。(就像我们购买电影票看电影,每张电影票上面都有对应的座位号,我们到电影院之后,只需要按照电影票上的座位号入座即可)如下图:
    Vue学习笔记---Vue中的虚拟DOM以及它 的Diff算法_第3张图片
    v-for中的key属性,一方面可以提高性能,另一方面还可以避免出错。
    参考:
    虚拟dom与key的关系
    虚拟DOM的框架/工具操作流程具体代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        //DOM节点在HTML文档中的表现形式
        <div id="content">
            <p>{{ 1+1}}</p>
            <ul class="list-group">
                
            </ul>
        </div>
        <script src="./base/vue.js"></script>
    
        <script>
            var data = {
                arr:[]
            }
    
            //1.内存中生成一棵虚拟dom树
            //用js代码表示DOM节点的伪代码
            var vDom = {
                tag:"div",
                attr:{
                    id:"content"
                },
                children:[
                    {tag:"p",content:2},
                    {tag:"ul",attrs:{className:"list-group"}}
                ]
            }
    
            //2.将内存中的虚拟dom树初始化渲染成真实dom树
            //3.更新虚拟DOM中data里面的数据
            data.arr.push("
  • 111111
  • "
    ) data.arr.push("
  • 222222
  • "
    ) //4.将之前的虚拟dom树结合新的数据生成一棵新的虚拟dom树 var newDom = { tag:"div", attr:{ id:"content" }, children:[ {tag:"p",content:2}, {tag:"ul",attrs:{className:"list-group"},children:[ {tag:"li",content:"11111"}, {tag:"li",content:"22222"} ]} ] } //5.将此次生成的新的虚拟dom树与上一次的虚拟dom树结构进行对比,对比差异(diff算法) //6.将对比出来的差异的部分进行重新真实dom结构的渲染

    你可能感兴趣的:(Vue学习笔记---Vue中的虚拟DOM以及它 的Diff算法)