Vue データ内のプロパティをランダムに変更すると、ビューは更新されますか?

Vue データ内のプロパティをランダムに変更すると、ビューは更新されますか?
  • インタビュアー: Vue のソースコードを読んだことはありますか?
  • 応募者:あります。
  • インタビュアー: では、 Vue dataのプロパティを変更すると、ビューは更新されますか?
  • 候補者:いいえ。
  • インタビュアー:なぜですか?
  • 候補: プロパティがテンプレートで使用されていない場合は、ビューを更新する必要はなく、頻繁に更新するとパフォーマンスが低下します。
  • インタビュアー: このソリューションを Vue でどのように実装しますか?
  • 候補: インスタンスの初期化中に、 Object.definePropertyを使用してデータ内のプロパティを監視します。プロパティがtemplateで使用されている場合、それらは Dep クラスによって収集され、プロパティが変更されると、notify が呼び出されてビューが更新されます。
  • インタビュアー: テンプレートでどの属性が使用されているかはどのようにしてわかりますか?
  • 候補者: 何だこれ。 。 。よく分かりません。説明していただけますか?
  • インタビュアー: では、簡単に説明させてください。

まずは簡単なdemoを書いてみましょう。データには 4 つの属性 a、b、c、d があり、テンプレートでは a と b のみが使用されます。 a と b だけが Dep に電話して回収するかどうかを確認します。

新しいVue({
  el: '#app',
  データ() {
    戻る {
      a: 1、
      b: 2,
      c: 3,
      d: 4,
    };
  },
  作成された() {
    コンソールにログ出力します。
    this.b = 'aaa';
  },
  テンプレート: '<div>Hello World{{a}}{{b}}</div>',
});


Vueinstance/state.jsでは、各属性をプロキシするためにプロキシが使用されます。

定数キー = Object.keys(データ)
  定数プロパティ = vm.$options.props
  const メソッド = vm.$options.methods
  i = キーの長さとする
  (i--) {
    定数キー = キー[i]
    もしprops && hasOwn(props, key) であれば
      process.env.NODE_ENV !== 'production' && 警告(
        `データ プロパティ "${key}" はすでにプロパティとして宣言されています。` +
        `代わりにプロパティのデフォルト値を使用してください。`,
        仮想
      )
    } そうでなければ (!isReserved(key)) {
      //プロキシオブジェクトのプロパティ proxy(vm, `_data`, key)
    }
  }
  // データを観察する
  観察(データ、true /* asRootData */)


データ内の各属性をハイジャックするには、defineReactive を使用します。

観察(データ、true /* asRootData */);

// 観察する
定数キー = Object.keys(obj);
(i = 0 とします; i < keys.length; i++) {
  Reactive を定義します (obj、キー [i])。
}

// リアクティブを定義する
Object.defineProperty(obj, キー, {
  列挙可能: true、
  設定可能: true、
  取得: 関数reactiveGetter() {
    const value = getter ? getter.call(obj): val;
    // 重要なポイントはここです。後でテンプレートで属性が使用される場合、reactiveGetter関数が実行されます // Depクラスによって収集されます if (Dep.target) {
      console.log(`${key} プロパティは Dep クラスによって収集されます`)
      依存関係
      if (childOb) {
        childOb.dep.depend();
        Array.isArray(値)の場合{
          依存配列(値);
        }
      }
    }
    戻り値;
  },
  設定: 関数reactiveSetter(newVal) {
    const value = getter ? getter.call(obj): val;
    /* eslint は自己比較を無効にします */
    if (newVal === 値 || (newVal !== newVal && 値 !== 値)) {
      戻る;
    }
    if (セッター) {
      // 計算されたセット関数は次のとおりです。setter.call(obj, newVal);
    } それ以外 {
      val = 新しいVal;
    }
    childOb = !shallow && observe(newVal);
    // プロパティを変更すると、notify を呼び出してビューを非同期的に更新します。dep.notify();
  },
});

$mountを実行してビューをマウントします

(vm.$options.el)の場合{
  vm.$mount(vm.$options.el);
}


$mount は Vue プロトタイプを呼び出すメソッドです。重要な点は最後の文 mount.call(this, el, hydrating) です。

Vue.prototype.$mount = 関数 (
  el?: 文字列 | 要素、
  水分補給?: ブール値
): 成分 {
  el = el && クエリ(el);

  const オプション = this.$options;
  // template/el を解決し、レンダリング関数に変換します
  /**
   * レンダリング関数が存在するかどうかを確認しますか?存在しない場合は、テンプレートを解析します。テンプレート* Vue がページをレンダリングする場合、2 つの方法があります: 1. テンプレート、2. レンダリング。最終的には、すべてのテンプレート クラスをレンダリングを使用してレンダリングする必要があります。*/
  if (!options.render) {
    テンプレートを options.template とします。
    if (テンプレート) {
      if (typeof テンプレート === '文字列') {
        (template.charAt(0) === '#')の場合{
          テンプレート = idToTemplate(テンプレート);
          /* イスタンブールは無視します */
          process.env.NODE_ENV !== 'production' && !template) の場合 {
            警告(
              `テンプレート要素が見つからないか空です: ${options.template}`,
              これ
            );
          }
        }
      } それ以外の場合 (template.nodeType) {
        テンプレート = template.innerHTML;
      } それ以外 {
        process.env.NODE_ENV !== 'production' の場合 {
          warn('無効なテンプレートオプション:' + template, this);
        }
        これを返します。
      }
    } そうでなければ (el) {
      // テンプレートが存在しない場合は、デフォルトの HTML テンプレートを作成します。 template = getOuterHTML(el);
    }
  }
  // Vue.prototype.$mount を書き換え、最後にキャッシュされた mount メソッドを呼び出して $mount のマウントを完了します。 return mount.call(this, el, hydrating);
};

ここで、mount は mountComponent(this, el, hydrating) メソッドを呼び出し、mountComponent は _render 関数を実行し、最後に _render は render を呼び出して vnode を生成します。

const { render, _parentVnode } = vm.$options;
vnode = render.call(vm._renderProxy、vm.$createElement);


最後の図は、 render関数がdemotemplateをレンダリングしていることを示しています。最終的には、2 つの属性 a と b のみが Dep クラスによって収集されます。

記事に間違いがありましたらご指摘いただければ、引き続き改善させていただきます。ありがとうございます。ソースコードをデバッグする必要がある場合は、ここをクリックして readme に従ってください。希望の星

これで、Vue データのプロパティを変更してビューを更新する方法に関するこの記事は終わりです。より関連性の高い Vue データ コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • vue data が関数である理由をご存知ですか?
  • vueはデータの問題を修正し、リアルタイムで操作を表示します
  • Vueサブコンポーネントはデータを変更したり操作を呼び出したりします
  • Vueデータ変数が相互に割り当てられた後のリアルタイム同期の解決手順

<<:  判定条件を使用してCSSファイルをインポートする

>>:  CSS を使用してボックスを水平方向と垂直方向に中央揃えする方法 (8 つの方法)

推薦する

select @@session.tx_read_only が DB に大量に出現するのはなぜですか?

問題を見つける上位の SQL ステートメントを取得すると、DB が大量のselect @@sessi...

JDKネイティブスレッドプールのバグを修正するTomcatの実装原理

処理能力と同時実行性を向上させるために、Web コンテナは通常、リクエストを処理するタスクをスレッド...

4つの柔軟なScssコンパイル出力スタイル

多くの人は、Scss を使用する瞬間からコンパイル方法を説明されてきました。したがって、コマンドのコ...

Alibaba Cloud Nginx はドメイン名アクセス プロジェクトを実装するために https を設定します (グラフィック チュートリアル)

ステップ1: サードパーティの信頼できるSSL証明書に署名するAlibaba Cloud で直接、無...

Vue.jsはコンポーネントを通じてアイコンを処理します

アイコン処理ソリューションこの記録の目的は、element-plus 以外のアイコンをコンポーネント...

JavaScript の new 演算子を自分で実装する方法

目次コンストラクタ新しいオペレーター自分で新しいものを実装するコンストラクタnew を導入する前に、...

MySql 学習ノートにおけるトランザクション分離レベルの詳細な説明

背景トランザクションについて話すとき、誰もがそれに精通している必要があります。MySQL データベー...

Next.js 入門チュートリアル

目次導入Next.jsプロジェクトを作成するNext.js プロジェクトを手動で作成するcreact...

Linux デバイス用ネットワーク ドライバーの紹介

有線ネットワーク: イーサネット 無線ネットワーク: 4G、WiFi、Bluetooth、5G 概要...

Win10 VM 仮想マシンに Mac OS10.14 を完璧にインストールする (グラフィック チュートリアル)

最近、Apple の記者会見を見てとても興奮したので、Mac システムを体験して Apple の素晴...

MySQL トランザクションと分離レベルの基本原理の簡単な分析

目次序文1. 取引の基本原則の簡単な分析原子性:持続性分離:一貫性: 2. 分離レベルの基本原理の分...

Ubuntu 18.04で国内ソースを変更する方法の例

Ubuntu はソースが中国からなのでダウンロード速度が比較的遅いです。CentOS と異なり、yu...

MySQL クラスター化インデックスのページ分割原理の分析例

この記事では、MySQL クラスター化インデックスのページ分割を例を使って説明します。ご参考までに、...

Vue ダイナミック バインディング アイコンの完全な手順

0 アイコンと画像の違いアイコンは文字であり、画像はバイナリ ストリームです。つまり、画像はアイコン...

Webフロントエンドのパフォーマンス最適化

ウェブフロントエンド最適化のベストプラクティス: コンテンツWebフロントエンド最適化のベストプラク...