vueのkeyを正しく理解するにはどうすればいいですか?

5896 ワード

現在の状況について、keyの役割は以下の通りです。
  • v-forパスは、id、uuidなどをkeyとして使用して、唯一の識別ノードは、仮想DOMレンダリング
  • を加速する。
  • 応答式システムは、傍受されたデータがなく、+new Date()で生成されたタイムスタンプをkeyとして、手動で強制的にレンダリングをトリガする

  • 場面が似たり寄ったりというのはありますが、2つ目は次のようなものです。
    
    <div :key="rerender">
      <span>Hello Vue.js !</span>
      <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent>
    </div>
    
    refresh(){
      this.rerender = + new Date();
    }
    では、vueの中のkeyに関する知識点はどうなりますか?
  • 公式API知識ポイント
  • 上の2つの使用シーンの背後の原理は何ですか?
  • keyのほかに、DOMを強制的に更新する方法がありますか?
  • 参考資料
  • 公式APIの知識点
  • はVue.jsの中で、keyは6つの特殊な属性のkeyで、ref、is、slot、slot-scope、scopeの中の一つです。
  • keyの値はnumberでもいいし、stringでもいいです。
  • keyは主にVueのvirtual DOMアルゴリズムに作用して、diff new nodes listとold nodes listの時に、VNodeを識別する手がかりとします。
  • keyを使用しない場合、Vueはアルゴリズムを使用します。elementの移動を最小化し、同じタイプのelementに対して、最大限に適当なところでpatchまたはreuseを作成します。
  • keyを使ったら、Vueはkeysの順にelementを記録します。すでにkeyを持っていたelementが現れないと直接removeまたはdestoryedになります。
  • 同一のparentを持つチルドレンはunique keysが必要です。keyを繰り返すとレンダーerrorを招きます。
  • 最もよく使われる使い方1:v-for
    
    <ul>
      <li v-for="item in items" :key="item.id">...</li>
    </ul>
    最も一般的な使い方2:elementまたはcomponentを強制的に置換する
  • トリガコンポーネントのlifecycle
  • transion
  • をトリガします。
    
    <transition>
     <span :key="text">{{ text }}</span>
    </transition>
    textが変化すると、はreplaccedによってpatch edではなく、transionがトリガされます。
    私の理解:
    textが変化した時、spanのkeyは変化しました。つまり、古いkeyを持っていたspanはもう現れなくなりました。新しい値を持っているtextがkeyとして現れた時、新しいkeyを持っているspanが現れました。古いkey spanが除去され、古いtransionも除去されます。
    上の2つの使用シーンの背後の原理は何ですか?
    公式APIの知識点を合わせて、文章の冒頭に出た場面を振り返ってみます。
    シーン1:v-for遍持続、id、uuidなどをkeyとして使用し、唯一の識別ノードは仮想DOMレンダリングを加速する。
    答え:
  • keyを使用しない場合、Vueはアルゴリズムを使用します。elementの移動を最小化し、同じタイプのelementに対して、最大限に適当なところでpatchまたはreuseを作成します。
  • keyを使ったら、Vueはkeysの順にelementを記録します。すでにkeyを持っていたelementが現れないと直接removeまたはdestoryedになります。
  • シーン2:応答式システムに傍受されたデータがなく、+new Date()で生成されたタイムスタンプをkeyとして、手動で強制的にレンダリングをトリガする。
    
    <div :key="rerender">
      <span>Hello Vue.js !</span>
      <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent>
    </div>
    
    refresh(){
      this.rerender = + new Date();
    }
    答え:
  • keyを使ったら、Vueはkeysの順にelementを記録します。すでにkeyを持っていたelementが現れないと直接removeまたはdestoryedになります。
  • refreshメソッドを呼び出した後、spanとcomplexComponentを含むdivのkeyが変化しました。つまり、古いkeyを持っていたdivがもう現れなくなりました。新しい値を持つrerenderがkeyとして現れたら、古いkey divが移動されます。古いspanとcomplexComponeponentが新たに描画されます。父の部品の新しいpropObjとpropArの新しいcomplexComponentを持ってレンダリングします。
  • 思考:
  • はどうしてpropObjとpropArrですか?
  • は、新しいプロpObjとプロpArの新しいcomplexComponentレンダリングを父のコンポーネントとして持っています。なぜ太めにしますか?
  • Vue.jsのobjとarrがデータの変化を検出できない場合がありますので、objは属性の追加と削除です。これは追加と削除の両方がトリガされていません。watchは外部更新を教えていません。arrは配列内要素の再割り当てまたはlength属性を修正します。ウォッチは外部に更新を教えていませんでした)。
    だから!新しいkeyを付与する方式によって、古いkey divを除去し、新しいkey divをレンダリングし、propObjとpropArはcomplexComponentコンポーネント内でもう一度生命周期を触発し、もう一度レンダリングする。この時、父コンポーネントのpropObjとpropArjs変数はすでに新しい値を獲得しました。DOMをトリガしなかっただけでなく、VNodeも再レンダリングしました。キーをリフレッシュしてフォースアップして、フォースUpdateと言えば、DOMを手動で強制更新することができます。
    key以外に、DOMを強制的に更新する方法がありますか?
    シーン:親コンポーネントは、サブコンポーネントに渡すデータを修正し、配列データの更新は、this.setによって更新されませんでした。どうすればいいですか?
    
    this.productImages.forEach((product) => {
     if (product.productId in this.productsState) {
      product.status = this.productsState[product.productId];
     }
    });
    this.$setを使用しないとデータを賦課できない理由は何ですか?
    Vue.jsにおいて、Arayに対する変化検出は原型をブロックする方式で実現されます。つまり、Push、pop、shift、unshift、splice、sort、reverse、fill、copyWithinに対して配列自体の内容を変える方法でブロッキングして、それに応えます。product.status=this.products State[product.productId]配列自体の変更をトリガーする方法がないので、rerenderはありません。
  • コンポーネントのkey
  • を更新します。
  • ドルforceUpdate方法
  • コンポーネントのkeyを更新します
    1.このキーはどこに入ればいいですか?
    this.productImagesの父要素に加えると良いです。
    データ転送に関わらず、更新が必要なelementに直接追加することもできます。
    2.何でキーを作りますか?
    今は荒っぽい+new Date()タイムスタンプでkey値を作っています。
    双方向結合の値をkey値としてもいいです。新旧のkey値が違っていれば大丈夫です。
    3.keyの原理は何ですか?
    vue.jsの仮想DOMアルゴリズムは、vNodeを更新する際に、古いvNodeリストから新しいvNodeノードと同じvNodeを検索して更新する必要があります。このプロセスが属性keyを設定すれば、プロセスは速くなります。
    その他の具体的な見解は上記の通りです。
    $forceUpdate方法
    この方法は親コンポーネントでのみ起動できます。手動でvueインスタンスを通知して再レンダリングします。
    
    // $forceUpdate  
    Vue.prototype.$forceUpdate = function () {
     const vm: Component = this
     if (vm._watcher) {
      vm._watcher.update()
     }
    }
    // update  
    /**
     * Subscriber interface.
     * Will be called when a dependency changes.
     */
    update () {
     /* istanbul ignore else */
     if (this.lazy) {
      this.dirty = true
     } else if (this.sync) {
      this.run()
     } else {
      queueWatcher(this)
     }
    }
    1.$forceUpdateで更新できる原理分析
    product.status=this.products State[product.productId]以降、実際にはこの時点でdepは変化していますが、Vue.js配列応答式の実現はプロトタイプチェーン方式のため、この変化は検出されていませんので、自動的にrerenderできません。したがって、私たちは$forceUpdateの方式を通じて、depを含むwatch上のudate方法を呼び出して、rerenderを実行します。
    2.サブアセンブリでイベントを傍受できますが、親コンポーネントはイベントを送信してからサブアセンブリだけを更新しますか?
    いけません。
    depは親コンポーネントのwatchとdepなので、サブアセンブリではなく、親コンポーネントのthis.productImagesが検出されていません。リアルタイムで更新されています。サブアセンブリの問題ではありません。
    参考資料
    https://vuejs.org/v2/api/#key
    https://vuejs.org/v2/api/#vm-…
    https://vuejs.org/v2/guide/co
    締め括りをつける
    以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考学習価値を持ってほしいです。ありがとうございます。