在vue内部的话,其实有虚拟dom
虚拟dom其实是里面内存型对象(js内存对象) 属于内存数据 真实dom的一层映射

var data = {
        arr:[]
    }

    1.内存中生成一颗虚拟dom树                                    
    var vDom = {
        tag:"div",一个div标签   
        attr:{有id个属性,属性名content
            id:"content"
        },
        children:[div下有个p标签,p标签的内容为2   和一个ul标签,ul标签有个class属性,属性名为list-group
            {tag:"p",content:2},
            {tag:"ul",attrs:{className:"list-group"}}
        ]
    }


    上面虚拟dom树相当于这个 <div ><p>2</p><ul ></ul></div>  结构的真实dom树,(html结构)


    2.将内存中的虚拟dom树初始化渲染成真实dom树
    3.当我们修改data里面的数据的时候
    data.arr.push("<li>111111</li>")
    data.arr.push("<li>222222</li>")
    4.将之前的虚拟dom树结合新的数据生成一颗新的虚拟dom树
    var newDom = {                                                                                                       
        tag:"div",   一个div标签                                                           
        attr:{有id个属性,属性名content
            id:"content"
        },
        children:[div下有个p标签,p标签的内容为2   和一个ul标签,ul标签有个class属性,属性名为list-group
            {tag:"p",content:2},
            {tag:"ul",attrs:{className:"list-group"},children:[
                {tag:"li",content:"11111"},ul标签下有两个li标签内容分别为11111,22222
                {tag:"li",content:"22222"}
            ]}
        ]
    }

上面数据发生改变之后生成的新的虚拟dom树相当于这个


2

  • 11111
  • 22222

结构的真实dom树,(html结构)

5.将此次生成好的新的虚拟dom树与上一次的虚拟dom树结构进行对比,对比差异(diff算法)

    同层对比,数据发生改变之后生成的新的虚拟dom树和旧的虚拟dom树对比,div和div对比,p和p对比ul和ul对比,如果div这个根节点不一样
    那么不会再往下对比,直接重新渲染整个虚拟dom树,如果div下的ul节点不同,那么li节点不会再对比,直接重新渲染发生改变之后的ul这个层级的dom结构
    节点类型不变,属性或者属性值改变,不会卸载节点,执行节点更新的操作。
    文本改变,直接修改文字内容。
    6.将对比出来的差异的部分进行重新真实dom结构的渲染

    (diff算法)如果想在中间插入节点F,简单粗暴的做法是:卸载C,装载F,卸载D,装载C,卸载E,装载D,装载E。如下图:

使用虚拟表格直接创建一个带有样式的表格 VUE elementui vue怎么创建虚拟dom_树结构


写代码时,如果没有给数组或枚举类型定义一个key,就会采用上面的粗暴算法。

如果为元素增加key后,Vue就能根据key,直接找到具体的位置进行操作,效率比较高。如下图:

使用虚拟表格直接创建一个带有样式的表格 VUE elementui vue怎么创建虚拟dom_树结构_02


v-for中的key属性

在v-for中提供key,一方面可以提高性能,一方面也会避免出错。

下面是一个出错的例子:

没有key:

比如本来选中的是"苹果": 但是添加了"核桃"之后,选中的就变成"核桃"了: 这是因为没有给元素添加key属性,从而在渲染的时候采用的是上面提到的简单粗暴的做法。卸载苹果",装载核桃,卸载香蕉",装载苹果,卸载橘子",装载香蕉,再装载橘子,因为选中的是第一个,核桃把苹果挤下去成为了第一个苹果变为了第二个,苹果把香蕉挤下去成为了第二个香蕉变为了第三个,以此类推橘子变为了最后一个

当给元素添加了key属性之后,就不会出现这样的问题了。要注意为每项提供一个具有唯一值的 key 属性。理想的 key 值是每项都有的唯一 id:



本来选中的是"苹果":
点击在数组前面添加了"核桃"之后,选中的仍然是"苹果":(key 值是每项都有的唯一 id:)
这是因为他是根据key值添加的选中状态,key为1的是选中的那么再添加一个key值为4的只是位置不同其他的该是什么还是什么

内部当数据变化,生成一颗新的虚拟dom树,与上一次的虚拟dom树结构进行对比。也就是说,当数据变化的时候,
        大量操作的是虚拟dom,而虚拟dom属于内存数据,操作起来性能要高的多。而真实的dom操作,只有在追加的那一刻
        才会进行操作,大大提升了性能。