首頁 > web前端 > js教程 > 主體

Vue.js中的computed工作原理

亚连
發布: 2018-05-26 16:38:09
原創
1532 人瀏覽過

這篇文章,我們透過實作一個簡單版的和Vue中computed具有相同功能的函數來了解computed是如何運作的。對Vue.js中的computed工作原理有興趣的朋友一起學習吧

#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的一個方法,第一個參數是物件名稱,第二個參數是要設定的屬性名,第三個參數是一個對象,它可以設定這個屬性是否可修改、可寫等,而這篇文章主要使用的是Obeject.defineProperty的存取器屬性,有興趣的朋友可以自行google或查看Js高及程式設計)

儘管person.age 看起來像是訪問了物件的一個屬性,但其實在內部我們是運行了一個函數。

一個基本上可回應的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' 這個值,而是getter這個函數擁有 '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);
登入後複製

讓我們寫一個簡單的 defineComputed 函數,它支援呼叫計算方法,但目前不需要它支援 updateCallback 。

function defineComputed (obj, key, computeFunc, updateCallback) {
 Object.defineProperty (obj, key, {
  get: function () {
   // 执行计算函数并且返回值
   return computeFunc ();
  },
  set: function () {
   // 什么也不做,不需要设定计算属性的值
  }
 })
}
登入後複製

這個函數有兩個問題:

每次存取計算屬性時都會執行一次計算函數computeFunc ()

它不知道何時更新(即當我們更新某個data中的屬性,計算屬性中也會更新這個data屬性)

// 我希望最终函数执行后是这个效果:每当person.age更新值的时候,person.status也同步更新
person.age = 17;
// console: status 的值为 minor
person.age = 22;
// console: status 的值为 adult
登入後複製

#增加一個依賴項

##讓我們增加一個全域變數Dep :

var Dep = {
 target: null
};
登入後複製

這是一個依賴項,接著我們用一個騷操作來更新defineComputed 函數:

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技術中servlet末尾的輸出流

Ajax php實作商品分類三級連動

Ajax技術組成與核心原理分析
#

以上是Vue.js中的computed工作原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!