key和diff算法
来自课程:https://ke.qq.com/course/3453141
1.1. 认识VNode和VDOM
在使用v-for进行列表渲染时,我们通常会给元素或者组件绑定一个key属性。
这个key属性有什么作用呢?我们先来看一下官方的解释:
- key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes;
- 如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法;
- 而使用key时,它会基于key的变化重新排列元素顺序,并且会移除/销毁key不存在的元素;
官方的解释对于初学者来说并不好理解,比如下面的问题:
- 什么是新旧nodes,什么是VNode?
- 没有key的时候,如何尝试修改和复用的?
- 有key的时候,如何基于key重新排列的?
我们先来解释一下VNode的概念:
- VNode的全称是Virtual Node,也就是虚拟节点;
- 事实上,无论是组件还是元素,它们最终在Vue中表示出来的都是一个个VNode;
- VNode的本质是一个JavaScript的对象;
<div class="title" style="font-size: 30px; color: red;">哈哈哈</div>在我们的Vue中会被转化创建出一个VNode对象:
const vnode = {
type: 'div',
props: {
'class': 'title',
style: { 'font-size': '30px', color: 'red' }
},
children: '哈哈哈'
}Vue内部在拿到vnode对象后,会对vnode进行处理,渲染成真实的DOM。
DOM渲染过程:

如果我们不只是一个简单的div,而是有一大堆的元素,那么它们应该会形成一个VNode Tree:
<div>
<p>
<i>哈哈哈哈</i>
<i>哈哈哈哈</i>
</p>
<span>嘻嘻嘻嘻</span>
<strong>呵呵呵呵</strong>
</div>
这个和我们的key有什么关系呢?
- 接下来我们就进行具体的分析;
1.2. key作用和diff算法
我们先来看一个例子:
- 这个例子是当我点击按钮时会在中间插入一个f;
<div id="app"></div>
<template id="my-app">
<ul>
<li v-for="item in letters">{{item}}</li>
</ul>
<button @click="insertF">insert f</button>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: "#my-app",
data() {
return { letters: ["a", "b", "c", "d"] };
},
methods: {
insertF() {
this.letters.splice(2, 0, "f");
},
},
};
Vue.createApp(App).mount("#app");
</script>我们可以确定的是,这次更新对于ul和button是不需要进行更新,需要更新的是我们li的列表:
- 在Vue中,更新前后都相同的元素节点并不会重新渲染;
- 对于列表中 a、b、c、d它们都是没有变化的;
- 在操作真实DOM的时候,我们只需要在中间插入一个f的li即可;
那么Vue中对于列表的更新究竟是如何操作的呢?
- Vue事实上会对于有key和没有key会调用两个不同的方法;
- 有key,那么就使用
patchKeyedChildren方法; - 没有key,那么就使用
patchUnkeyedChildren方法;

1.3. 没有key执行操作
没有key对应的源代码如下:

它的过程画图就是如下的操作:

我们会发现上面的diff算法效率并不高:
- c和d来说它们事实上并不需要有任何的改动;
- 但是因为我们的c被f所使用了,所有后续所有的内容都要一次进行改动,并且最后进行新增;
1.4. 有key执行操作
如果有key,那么会执行什么样的操作呢?

第一步的操作是从头开始进行遍历、比较:
- a和b是一致的会继续进行比较;
- c和f因为key不一致,所以就会break跳出循环;
第一步对比的过程
第二步的操作是从尾部开始进行遍历、比较:
第二步对比过程
第三步是如果旧节点遍历完毕,但是依然有新的节点,那么就新增节点:

第四步是如果新的节点遍历完毕,但是依然有旧的节点,那么就移除旧节点:

第五步是最特色的情况,中间还有很多未知的或者乱序的节点:

所以我们可以发现,Vue在进行diff算法的时候,会尽量利用我们的key来进行优化操作:
- 在没有key的时候我们的效率是非常低效的;
- 在进行插入或者重置顺序的时候,保持相同的key可以让diff算法更加的高效;
Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.
1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino
我一直梦想, 看到你们相册那样的地方。真棒。
我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。
我热爱这样的想法, 去那么多国家。真的很鼓舞。
能感受到热爱。继续保持 感受。
我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。
1
1
1