Vue 中虚拟DOM与key属性

本文介绍了Vue中虚拟DOM的原理流程,包括用JavaScript模拟DOM树、Diff算法的应用,以及v-for指令中key属性的重要作用。通过Diff算法,Vue能够高效地更新DOM,而key属性则进一步优化了列表渲染的性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.虚拟DOM的原理流程:

1.用JavaScript模拟DOM树,并且渲染这个DOM树
2.在实现的过程中比较新老DOM树,得到比较差异的对象
3.然后把差异的对象应用到渲染的DOM树。

下面是流程图:
在这里插入图片描述
虚拟的DOM的核心思想就是:对复杂的文档DOM结构,提供一种方便的工具,进行最小化的DOM操作。这句话过于抽象,却基本概括了虚拟DOM的设计思想。也就是说根据虚拟dom树最初渲染成真实dom,当数据变化,或者说是页面需要重新渲染的时候,会重新生成一个新的完整的虚拟dom,拿新的虚拟dom来和旧的虚拟dom做对比(使用diff算法),得到需要更新的地方之后,更新内容这样的话,就能大量减少真实dom的操作,提高性能。

1.1.实现虚拟DOM

下面是一个真实的DOM节点

 <div id="my-heard">
        <p>hello world</p>
        <ul>
            <li class="num">num1</li>
            <li class="num">num2</li>
            <li class="num">num3</li>
        </ul>
    </div>

下面用内存型对象(js内存对象)模拟DOM节点实现虚拟DOM。

 let data = {
            arr: []
        }
        //1.内存中生成一颗虚拟dom树
        var VDom = {
            tag: "div",
            attr: {
                id: "my-heard"
            },
            children: [
                { tag: "p", text: helloWorld },
                { tag: "ul", attrs: { className: "list-ul" } }
            ]
        }
        //2.将内存中的虚拟dom树初始化渲染成真实dom树
        //3.当我们修改data里面的数据的时候
        data.arr.push("<li>我是第一个li</li>")
        data.arr.push("<li>我是第二个li</li>")
        //4.将之前的虚拟dom树结合新的数据生成一颗新的虚拟dom树
        var newDom = {
            tag:"div",
            attr:{
                id:"my-heard"
            },
            children:[
                {tag:"p",text:helloWorld},
                {tag:"ul",attrs:{clasName:"list-ul"},children:[
                    {tag:"li",text:"我是第一个li"},
                    {tag:"li",text:"我是第一个li"}
                ]}
            ]
        }
2.虚拟DOM的Diff算法

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

Diff有以下4种情况:
1.如果节点类型改变,直接将旧节点卸载,替换为新节点,旧节点包括下面的子节点都将被卸载,如果新节点和旧节点仅仅是类型不同,但下面的所有子节点都一样时,这样做也是效率不高的一个地方。
2.节点类型不变,属性或者属性值改变,不会卸载节点,执行节点更新的操作。
3.文本改变,直接修改文字内容。
4.移动,增加,删除子节点时:
在这里插入图片描述
2-1:如果想在中间插入节点F,简单粗暴的做法是:卸载C,装载F,卸载D,装载C,卸载E,装载D,装载E。如下图:
在这里插入图片描述
2-2:如果为元素增加key后,Vue就能根据key,直接找到具体的位置进行操作,效率比较高。如下图:
在这里插入图片描述

3.v-for中的key属性

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

下面是vue中v-for不绑定key:Vue的v-for不绑定key,默认行为和绑定key="index"是差不多的,官方没有默认这种行为的情况下,会导致所有列表DOM重新渲染。key="index"这种行为无法最大化性能,比如在第一个元素插入新元素,会导致所有列表DOM重新渲染。绑定key后,发现绑定的key值的元素变化了,就重新渲染该元素,而不是全部元素都重新渲染,会提高性能。性能主要是DOM渲染影响。key绑定id一类的唯一键好处就是在列表中插入某个元素,不会像index那样导致后面的元素全部重新渲染,而是根据绑定id的元素是否变化渲染。

 <div id="app">
    <div>
        <button @click="add">添加</button>
    </div>
    <ul>
        <li v-for="item  in arr" ><input type="checkbox">{{item}}</li>
    </ul>

   </div>


   <script src="../base/vue.js"></script>
   <script>
       new Vue({
           el:"#app",
           data:{
                arr:["华山派","武当派","峨嵋派"]
           },
           methods:{
               add(){
                    this.arr.unshift("少林派")
               }
           }
       })


一开始选中的是"华山派":
在这里插入图片描述
但是添加了"少林派"之后,选中的就变成"少林派"了:
在这里插入图片描述
这是因为没有给元素添加key属性,从而在渲染的时候采用的是上面提到的2-1的做法。

下面是vue中v-for绑定key:这个就地复用原则是指 如果数据项的顺序被改变,vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素

 <div id="app">
    <div>
        <button @click="add">添加</button>
    </div>
    <ul>
        <li v-for="(item,index) in arr" :key="item.id"><input type="checkbox">{{item}}</li>
    </ul>

   </div>


   <script src="../base/vue.js"></script>
   <script>
       new Vue({
           el:"#app",
           data:{
                arr:[
                  {name:"华山派",id:1},
                  {name:"武当派",id:2},
                  {name:"峨嵋派",id:3},
            ]
           },
           methods:{
               add(){
                    this.arr.unshift( {name:"少林派",id:3})
               }
           }
       })

一开始选中的是"华山派":
在这里插入图片描述
添加了"少林派"之后,选中的还是变成"华山派"了:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值