この記事では、Vuejs の主要な値に関する関連知識を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。
数日前に記事を書きました。 sortable.js - Vue データ更新の問題その時は、強制リフレッシュの観点からデータを分析しただけで、本当の「犯人」は見つかりませんでした。
データが正しく表示されない原因は Vue
の key
値である可能性があることを指摘していただき、大変助かりました。そこから、さらなる試みをしてみました。 [関連する推奨事項: "vue.js チュートリアル "]
index
を key
##v-for を記述するときに、
index を
key の値として直接使用するかどうかはわかりません。はい、使用することは認めます。これは本当に良い習慣とは言えません。
sortable.js を例として使用して説明します。以下はコアコードです。
arrData の値は [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) } }) }
key の値を変更しました。この例は非常に特殊なので、
item の値は異なると思います
<div id="sort"> <div v-for="(item,index) in arrData" :key="item" > <div>{{item}}</div> </div> </div>
key
の紹介を見てください同じ親要素を持つ子要素は一意のキーを持つ必要があります。キーが重複するとレンダリング エラーが発生します。
値が一意ではないためです。たとえば、上記の上記のレンダリング エラーが発生する理由は、
key
key 値は、配列の作成時に調整されます。注文後、各アイテムの元の
key 値が変更され、レンダリング エラーが発生します。
まず結論を導き出します。
index を key
値として使用することには隠れた危険があります。 ## は常に一意の識別子として使用できますかキー値の用途は何ですか
その場合、warning
が報告されます。これは、公式が key
の値を書き込むように求めているため、key
がvue
それはどのような役割を果たしましたか? キーを使用せずにパフォーマンスを向上させることはできますか?
答えは「はい」です。できる!
最初に公式の説明を見てみましょう:
キーが使用されていない場合、Vue は動的要素を最小限に抑えるアルゴリズムを使用し、同じタイプの要素を修復/再利用しようとします。できるだけ。キーを使用すると、キーの変更に基づいて要素の順序が並べ替えられ、キーが存在しない要素が削除されます。たとえば、配列 [1,2,3,4] が [2,1,3,4] になる場合、key
のない値は次の形式になります。 「インプレース更新戦略」については、次の図を参照してください。要素ノードの位置は移動しませんが、要素自体を直接変更するため、パフォーマンスがいくらか節約されます。
key 値を持つ要素の場合、その更新方法を次の図に示します。ご覧のとおり、ここでは DOM に対する削除/追加操作が行われており、比較的パフォーマンスを消費します。
key
を使用しない方がパフォーマンスが向上します。なぜキーを使用する必要があるのですか まず例を見てみましょう。コードは次のとおりです。これは、tab 那么当我们点击tab1将字体色设置成红色之后,再切换到 tab2,我们预期的结果是我们第一项字体的初始颜色而不是红色,但是结果却还是红色。 这就超出了我们的预期了,也就是官方文档所说的,默认模式指的就是不带 这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。 我们来看带上 这就是官方文档之所以推荐我们写 使用 那么 这里我们不谈 看 我们整理一下代码块: 那么最主要还是 を切り替える関数を模倣します。つまり、切り替えられる tab1 は 1,2,3,4 です。 tab2 は 5、6、7、8 です。最初の項目をクリックすると文字色を赤色に設定する機能があります。
<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 状态的,这种模式是不适用的。key
之后的效果key
的原因,根据文档的介绍,如下:key
,它会基于 key
的变化重新排列元素顺序,并且会移除 key
不存在的元素。
它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景的时候它可能会很有用:Vue
底层 key
值到底是怎么去做到以上的功能?我们就得聊聊 diff
算法以及虚拟 DOM
了。key 在 diff 算法中的作用
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
中相对应的节点。
更多编程相关知识,请访问:编程视频!!
以上がVuejs の主要な値の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。