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 つの方法)

推薦する

ウェブページ読み込み時に左右にジャンプする原因の分析と解決

最近、ウェブサイトを設計するときにこの問題に遭遇しています。メンバーセンターを設計し、コンテンツを ...

JSタイマーを使用して要素を移動する

JS タイマーを使用して、要素に移動する効果のあるメソッドを作成します。実装のアイデアは、まず要素の...

LinuxカーネルとSVNバージョン間の競合の解決策

現象システムは Linux システムカーネルを正常にコンパイルできましたが、SVN をインストールし...

MySQLのクラスタ化インデックスと非クラスタ化インデックスの詳細な説明

1. クラスター化インデックステーブル データはインデックスの順序で保存されます。つまり、インデック...

MySQLで大きなテーブルを正常に削除する方法の詳細な説明

序文テーブルを削除するには、無意識に思い浮かぶコマンドは、DROP TABLE "テーブル...

Ubuntu で apt-get を使用して mysql をインストールおよび完全にアンインストールする方法の詳細な説明

1. mysqlをインストールします。 udo apt-getでmysql-serverをインストー...

nginx のロードバランシングとリバースプロキシの説明

目次負荷分散負荷分散分類1. DNS 負荷分散2. IP負荷分散3. リンク層の負荷分散4. ハイブ...

Vue axios インターセプターは、繰り返しリクエストのキャンセルによく使用されます。

導入前回の記事では、axios のシンプルなカプセル化と、axios インターセプターの適用シナリオ...

Windows10 での MySQL msi インストール チュートリアル (画像とテキスト付き)

1. ダウンロード1. MySQL msi 公式 Web サイトから最新のダウンロードをクリックす...

Docker に MySQL と MariaDB をインストールする方法

MySQLとMariaDBの関係MariaDB データベース管理システムは MySQL のブランチで...

SQL の左結合と右結合の原理と例の分析

テーブルが 2 つあり、テーブル A のレコードがテーブル B に存在しない可能性があります。左結合...

OCSP を有効にすると、https 証明書の検証効率が向上し、Let's Encrypt SSL 証明書へのアクセスが遅くなる問題が解決されます。

ここ数日、ウェブサイトを初めて開いたときにアクセスが非常に遅いのですが、その後はページが正常に開きま...

ウェブページ制作時のコードコメントの書き方

<br />私の仕事で使用しているアノテーションの書き方の基準をまとめました。技術的な内...

LinuxのCPU負荷とCPU使用率の詳細な説明

CPU 負荷と CPU 使用率これらは両方とも、ある程度、マシンの忙しさを反映できます。 CPU 使...

MAC での MYSQL5.7.17 接続失敗の問題と解決策

MYSQL5.7.17 が MAC で接続できない問題。SQLBench_community 6.3...