Cet article vous présentera les connaissances pertinentes sur les valeurs clés dans Vuejs. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.
J'ai écrit un article il y a quelques jours, sortable.js - Problème de mise à jour des données Vue À cette fois-là, je n'ai analysé les données que du point de vue d'un rafraîchissement forcé, et je n'ai pas trouvé le vrai « coupable ».
Merci beaucoup pour quelqu'un qui m'a aidé à souligner que c'est peut-être la Vue
valeur de key
qui provoque un rendu incorrect des données. À partir de là, j’ai fait d’autres tentatives. [Recommandation associée : "Tutoriel vue.js"] Une utilisation incorrecte de la
index
comme key
Je ne sais pas ce que vous j'écrisv-for
, vais-je utiliser directement index
comme valeur key
Oui, j'avoue que je le ferai, je dois dire, ce n'est vraiment pas une bonne habitude.
Sur la base de l'article précédent, nous utilisons toujours sortable.js
comme exemple pour discuter. Ce qui suit est le code de base, où la valeur de arrData
est [1,2,3,4]
<div id="sort"> <div v-for="(item,index) in arrData" :key="index" > <div>{{item}}</div> </div> </div>
mounted () { let el = document.getElementById('sort') var sortable = new Sortable(el, { onEnd: (e) => { const tempItem = this.arrData.splice(e.oldIndex, 1)[0] this.arrData.splice(e.newIndex, 0, tempItem) } }) }
Bien sûr, il n'y aura aucun problème avec le rendu des données au début
Bon, regardons les opérations suivantes :
Comme vous je peux voir, je le ferai. Lorsque 3 est glissé au-dessus de 2, les données ci-dessous deviennent 1342, mais celle affichée ci-dessus est toujours 1234. Ensuite, lorsque j'ai fait glisser la quatrième position vers la troisième position, les données ci-dessous ont également pris effet, mais les données ci-dessus semblaient toutes foirées. Super, nous avons recréé la scène du crime.
Ensuite, j'ai changé la valeur liée key
Parce que l'exemple ici est assez spécial, nous pensons que les valeurs de item
sont différentes
<div id="sort"> <div v-for="(item,index) in arrData" :key="item" > <div>{{item}}</div> </div> </div>
Regardez l'effet :
Oui, à ce moment, les données sont complètement synchronisées avec la vue.
Pourquoi ?
Premier coup d'œil à l'introduction de key
dans la documentation officielle
Les éléments enfants avec le même élément parent doivent avoir des clés uniques. Les clés en double entraîneront des erreurs de rendu.
provoque l'erreur de rendu ci-dessus car notre valeur key
n'est pas unique. Par exemple, la valeur key
ci-dessus modifiera la valeur d'origine de chaque élément après avoir ajusté l'ordre du tableau <. 🎜> les valeurs ont changé, entraînant des erreurs de rendu. key
Il existe des dangers cachés à utiliser comme valeur de index
à moins que vous ne puissiez garantir que key
peut toujours être utilisé comme identifiant unique index
, si nous n'écrivons pas vue2.0
, il rapportera key
, ce qui signifie que le fonctionnaire veut que nous écrivions warning
valeur Oui, alors quel rôle key
joue-t-il dans key
? vue
Les performances peuvent-elles être améliorées sans utiliser de clés La réponse est oui ! Peut!
Regardez d'abord l'explication officielle :Si les clés ne sont pas utilisées, Vue utilisera un algorithme qui minimise les éléments dynamiques et essaiera de réparer/réutiliser autant que possible les éléments du même type. que possible. À l'aide de key, il réorganise l'ordre des éléments en fonction des changements de clé et supprime les éléments là où la clé n'existe pas.Par exemple, si un tableau [1,2,3,4] devient [2,1,3,4], alors la valeur sans
prendra un "sur place" Stratégie de mise à jour", voir l'image ci-dessous. Elle ne déplace pas la position du nœud de l'élément, mais modifie directement l'élément lui-même, économisant ainsi quelques performances key
valeurs, sa mise à jour La méthode est illustré dans la figure ci-dessous. Comme vous pouvez le constater, il s'agit ici d'une opération de suppression/ajout au DOM, relativement gourmande en performances. key
n'a en fait pas Les performances sont meilleures, pourquoi devons-nous apporter la clékey
Regardons d'abord un exemple Le noyau. Le code est le suivant. Voici une imitation d'un commutateur La fonction de , c'est-à-dire que l'onglet1 à changer est 1,2,3,4. tab2 est 5,6,7,8. Il existe une fonction permettant de définir la couleur de police du premier élément sur rouge en cliquant dessus. tab
那么当我们点击tab1将字体色设置成红色之后,再切换到 tab2,我们预期的结果是我们第一项字体的初始颜色而不是红色,但是结果却还是红色。
<div id="sort"> <button @click="trunToTab1">tab1</button> <button @click="trunToTab2">tab2</button> <div v-for="(item, index) in arrData"> <div @click="clickItem(index)" class="item">{{item}}</div> </div> </div>
trunToTab1 () { this.arrData = [1,2,3,4] }, trunToTab2 () { this.arrData = [5,6,7,8] }, clickItem () { document.getElementsByClassName('item')[0].style.color = 'red' }
这就超出了我们的预期了,也就是官方文档所说的,默认模式指的就是不带 key
的状态,对于依赖于子组件状态或者临时 DOM 状态的,这种模式是不适用的。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
我们来看带上 key
之后的效果
这就是官方文档之所以推荐我们写 key
的原因,根据文档的介绍,如下:
使用
key
,它会基于key
的变化重新排列元素顺序,并且会移除key
不存在的元素。 它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景的时候它可能会很有用:
- 完整地触发组件的生命周期钩子
- 触发过渡
那么 Vue
底层 key
值到底是怎么去做到以上的功能?我们就得聊聊 diff
算法以及虚拟 DOM
了。
这里我们不谈 diff
算法的具体,只看 key
值在其中的作用。(diff
算法有机会我们再聊)
看 vue
源码中 src/core/vdom/patch.js
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx) idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
我们整理一下代码块:
// 如果有带 key if (isUndef(oldKeyToIdx)) { // 创建 index 表 oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); } if (isDef(newStartVnode.key)) { // 有 key ,直接从上面创建中获取 idxInOld = oldKeyToIdx[newStartVnode.key] } else { // 没有key, 调用 findIdxInOld idxInOld = findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx); }
那么最主要还是 createKeyToOldIdx
和 findIdxInOld
两个函数的比较,那么他们做了什么呢?
function createKeyToOldIdx (children, beginIdx, endIdx) { let i, key const map = {} for (i = beginIdx; i <= endIdx; ++i) { key = children[i].key if (isDef(key)) map[key] = i } return map }
function findIdxInOld (node, oldCh, start, end) { for (let i = start; i < end; i++) { const c = oldCh[i] if (isDef(c) && sameVnode(node, c)) return i } }
我们可以看到,如果我们有 key
值,我们就可以直接在 createKeyToOldIdx
方法中创建的 map
对象中根据我们的 key
值,直接找到相应的值。没有 key
值,则需要遍历才能拿到。相比于遍历,映射的速度会更快。
key
值是每一个 vnode
的唯一标识,依靠 key
,我们可以更快的拿到 oldVnode
中相对应的节点。
更多编程相关知识,请访问:编程视频!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!