ホームページ  >  記事  >  ウェブフロントエンド  >  Vuejs の主要な値の詳細な分析

Vuejs の主要な値の詳細な分析

青灯夜游
青灯夜游転載
2021-06-02 14:14:492503ブラウズ

この記事では、Vuejs の主要な値に関する関連知識を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

Vuejs の主要な値の詳細な分析

前回の記事から始まります

数日前に記事を書きました。 sortable.js - Vue データ更新の問題その時は、強制リフレッシュの観点からデータを分析しただけで、本当の「犯人」は見つかりませんでした。

データが正しく表示されない原因は Vuekey 値である可能性があることを指摘していただき、大変助かりました。そこから、さらなる試みをしてみました。 [関連する推奨事項: "vue.js チュートリアル "]

key の誤った使用 - indexkey

# として使用します

##v-for を記述するときに、indexkey の値として直接使用するかどうかはわかりません。はい、使用することは認めます。これは本当に良い習慣とは言えません。

前の記事に基づいて、引き続き

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(&#39;sort&#39;)
    var sortable = new Sortable(el, {
      onEnd: (e) => {
        const tempItem = this.arrData.splice(e.oldIndex, 1)[0]
        this.arrData.splice(e.newIndex, 0, tempItem)
      }
    })
  }

です。 もちろん、最初はデータに問題がないはずです。レンダリング

Vuejs の主要な値の詳細な分析

#それでは、次の操作を見てみましょう:

Vuejs の主要な値の詳細な分析

はい、2 の上に 3 をドラッグすると、下のデータは 1342 になりますが、上のビューは 1234 のままであることがわかります。次に、4 番目の位置を 3 番目の位置にドラッグすると、下のデータも有効になりましたが、上のデータはすべてめちゃくちゃになっているように見えました。素晴らしい、犯罪現場を再現しました。

次に、バインドされた

key の値を変更しました。この例は非常に特殊なので、item の値は異なると思います

<div id="sort">
  <div v-for="(item,index) in arrData" :key="item" >
    <div>{{item}}</div>
  </div>
</div>

エフェクトをもう一度見てください:

Vuejs の主要な値の詳細な分析

はい、この時点でデータはビューと完全に同期されています。 ######なぜ?

まずは公式ドキュメントの

key

の紹介を見てください

同じ親要素を持つ子要素は一意のキーを持つ必要があります。キーが重複するとレンダリング エラーが発生します。

上記のレンダリング エラーが発生する理由は、

key
値が一意ではないためです。たとえば、上記の

key 値は、配列の作成時に調整されます。注文後、各アイテムの元の key 値が変更され、レンダリング エラーが発生します。 まず結論を導き出します。

index# を確実にできない限り、

indexkey 値として使用することには隠れた危険があります。 ## は常に一意の識別子として使用できますかキー値の用途は何ですか

vue2.0

の後には記述しません

key

その場合、warning が報告されます。これは、公式が key の値を書き込むように求めているため、keyvue それはどのような役割を果たしましたか? キーを使用せずにパフォーマンスを向上させることはできますか?答えは「はい」です。できる!

最初に公式の説明を見てみましょう:

キーが使用されていない場合、Vue は動的要素を最小限に抑えるアルゴリズムを使用し、同じタイプの要素を修復/再利用しようとします。できるだけ。キーを使用すると、キーの変更に基づいて要素の順序が並べ替えられ、キーが存在しない要素が削除されます。

たとえば、配列 [1,2,3,4] が [2,1,3,4] になる場合、

key

のない値は次の形式になります。 「インプレース更新戦略」については、次の図を参照してください。要素ノードの位置は移動しませんが、要素自体を直接変更するため、パフォーマンスがいくらか節約されます。

また、

keyVuejs の主要な値の詳細な分析 値を持つ要素の場合、その更新方法を次の図に示します。ご覧のとおり、ここでは DOM に対する削除/追加操作が行われており、比較的パフォーマンスを消費します。

Vuejs の主要な値の詳細な分析key

を使用しない方がパフォーマンスが向上します。なぜキーを使用する必要があるのですか

まず例を見てみましょう。コードは次のとおりです。これは、tab を切り替える関数を模倣します。つまり、切り替えられる tab1 は 1,2,3,4 です。 tab2 は 5、6、7、8 です。最初の項目をクリックすると文字色を赤色に設定する機能があります。

那么当我们点击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(&#39;item&#39;)[0].style.color = &#39;red&#39;
      }

Vuejs の主要な値の詳細な分析

这就超出了我们的预期了,也就是官方文档所说的,默认模式指的就是不带 key 的状态,对于依赖于子组件状态或者临时 DOM 状态的,这种模式是不适用的。

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。

我们来看带上 key 之后的效果

Vuejs の主要な値の詳細な分析

这就是官方文档之所以推荐我们写 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);
  }

那么最主要还是 createKeyToOldIdxfindIdxInOld 两个函数的比较,那么他们做了什么呢?

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 サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。