Vue.js での計算の仕組み

亚连
リリース: 2018-05-26 16:38:09
オリジナル
1540 人が閲覧しました

この記事では、Vue での computed と同じ機能を持つ関数の単純なバージョンを実装することで、computed がどのように機能するかを理解します。 Vue.js で計算がどのように機能するかに興味のある友人は、一緒に学ぶべきです

JS プロパティ:

JavaScript には、多くのことを実行できる機能 Object.defineProperty がありますが、この記事ではこれにのみ焦点を当てます。メソッド:

var person = {};
Object.defineProperty (person, 'age', {
 get: function () {
  console.log ("Getting the age");
  return 25;
 }
});
console.log ("The age is ", person.age);
// Prints:
//
// Getting the age
// The age is 25
ログイン後にコピー

(Obeject.defineProperty は Object のメソッドです。最初のパラメータはオブジェクト名、2 番目のパラメータは設定するプロパティの名前、3 番目のパラメータはこのプロパティを設定できるオブジェクトです変更できるかどうか、書き込み可能かどうかなど。この記事では主に Object.defineProperty の accessor プロパティを使用します。興味のある方は Google または JS High や Programming を参照してください)

person.age はオブジェクトの access A プロパティのように見えますが、内部的には関数を実行しています。

基本的にレスポンシブな Vue.js

Vue.js は、通常のオブジェクトを監視できる値 (レスポンシブ属性) に変換できるオブジェクトを内部的に構築します。 ここでは、レスポンシブ属性を追加する方法の簡略版を示します。 :

function defineReactive (obj, key, val) {
 Object.defineProperty (obj, key, {
  get: function () {
   return val;
  },
  set: function (newValue) {
   val = newValue;
  }
 })
};
// 创建一个对象
var person = {};
// 添加可响应的属性"age"和"country"
defineReactive (person, 'age', 25);
defineReactive (person, 'country', 'Brazil');
// 现在你可以随意使用person.age了
if (person.age < 18) {
 return &#39;minor&#39;;
}
else {
 return &#39;adult&#39;;
}
// 设置person.country的值
person.country = &#39;Russia&#39;;
ログイン後にコピー

興味深いことに、25 と 'Brazil' は依然としてクロージャ内の変数であり、val は新しい値が割り当てられた場合にのみ変更されます。 person.country には値「Brazil」がありませんが、ゲッター関数には値「Brazil」があります。

計算されたプロパティを宣言する

計算されたプロパティを定義する関数defineComputedを作成しましょう。この機能は通常computedを使用する場合と同じです。

defineComputed (
 person, // 计算属性就声明在这个对象上
 &#39;status&#39;, // 计算属性的名称
 function () { // 实际返回计算属性值的函数
  console.log ("status getter called")
  if (person.age < 18) {
   return &#39;minor&#39;;
  }
  else {
   return &#39;adult&#39;;
  }
 },
 function (newValue) {
  // 当计算属性值更新时调用的函数
  console.log ("status has changed to", newValue)
 }
});
// 我们可以像使用一般的属性一样使用计算属性
console.log ("The person&#39;s status is: ", person.status);
ログイン後にコピー

compute メソッドの呼び出しをサポートする単純な defineComputed 関数を作成しましょう。ただし、現時点では updateCallback をサポートする必要はありません。

function defineComputed (obj, key, computeFunc, updateCallback) {
 Object.defineProperty (obj, key, {
  get: function () {
   // 执行计算函数并且返回值
   return computeFunc ();
  },
  set: function () {
   // 什么也不做,不需要设定计算属性的值
  }
 })
}
ログイン後にコピー

この関数には 2 つの問題があります:

計算関数 computeFunc () は、計算された属性にアクセスされるたびに実行されます

いつ更新するかがわかりません (つまり、特定のデータの属性を更新するとき、計算された属性も更新されます)

// 我希望最终函数执行后是这个效果:每当person.age更新值的时候,person.status也同步更新
person.age = 17;
// console: status 的值为 minor
person.age = 22;
// console: status 的值为 adult
ログイン後にコピー

依存関係を追加します

グローバル変数 Dep:

var Dep = {
 target: null
};
ログイン後にコピー

これは依存関係を追加しましょう。そして、クールな操作を使用して、defineComputed を更新しますfunction:

function defineComputed (obj, key, computeFunc, updateCallback) {
 var onDependencyUpdated = function () {
  // TODO
 }
 Object.defineProperty (obj, key, {
  get: function () {
   // 将onDependencyUpdated 这个函数传给Dep.target
   Dep.target = onDependencyUpdated;
   var value = computeFunc ();
   Dep.target = null;
  },
  set: function () {
   // 什么也不做,不需要设定计算属性的值
  }
 })
}
ログイン後にコピー

次に、前に設定した応答プロパティに戻りましょう:

function defineReactive (obj, key, val) {
 // 所有的计算属性都依赖这个数组
 var deps = [];

 Object.defineProperty (obj, key, {
  get: function () {
   // 检查是否调用了计算属性,如果调用了,Department.target将等于一个onDependencyUpdated函数
   if (Dep.target) {
    // 把onDependencyUpdated函数push到deos中
    deps.push (target);
   }

   return val;
  },
  set: function (newValue) {
   val = newValue;

   // 通知所有的计算属性,告诉它们有个响应属性更新了
   deps.forEach ((changeFunction) => {
    changeFunction ();
   });
  }
 })
};
ログイン後にコピー

計算されたプロパティによって定義された関数が更新コールバックをトリガーした後、onDependencyUpdated 関数を更新できます。

var onDependencyUpdated = function () {
 // 再次计算 计算属性的值
 var value = computeFunc ();
 updateCallback (value);
}
ログイン後にコピー

それらをまとめてみましょう:

計算された属性 person.status:

person.age = 22;
defineComputed (
 person,
 &#39;status&#39;,
 function () {
  if (person.age > 18) {
   return &#39;adult&#39;;
  }
 },
 function (newValue) {
  console.log ("status has changed to", newValue)
 }
});
console.log ("Status is ", person.status);
ログイン後にコピー

をもう一度見てみましょう。上記は、皆さんのために私がまとめたものです。将来皆さんのお役に立てれば幸いです。

関連記事:

Ajax技術におけるサーブレット終了時の出力ストリームについて

Ajax+phpで商品分類の3段階連携を実現

Ajax技術構成と核原理分析

以上がVue.js での計算の仕組みの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート