Vue.js学习之computed的工作原理详解

Vue.js前端开发中非常重要的一门语言,本文和大家分享的就是Vue.js中的computed相关内容,希望通过本文的分享能帮助大家更好的掌握和学习Vue.js

  本文将通过实现一个简单版的和Vuecomputed具有相同功能的函数来了解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.definePropertyObject的一个方法,第一个参数是对象名称,第二个参数是要设置的属性名,第三个参数是一个对象,它可以设置这个属性是否可修改、可写等,而这篇文章主要使用的是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.ageif (person.age < 18) {

  return 'minor';

  }else {

  return 'adult';

  }

  // 设置person.country的值

  person.country = 'Russia';

  有趣的是, 25  ‘Brazil’ 还是一个闭包内部的变量,只有当赋给它们新值的时候 val 才会改变。 person.country 并不拥有 'Brazil' 这个值,而是getter这个函数拥有 'Brazil' 这个值。

  声明一个计算属性

  让我们创建一个定义计算属性的函数 defineComputed 。这个函数就跟大家平时使用computed时的一样。

  defineComputed (

  person, // 计算属性就声明在这个对象上

  'status', // 计算属性的名称

  function () { // 实际返回计算属性值的函数

  console.log ("status getter called")

  if (person.age < 18) {

  return 'minor';

  }

  else {

  return 'adult';

  }

  },

  function (newValue) {

  // 当计算属性值更新时调用的函数

  console.log ("status has changed to", newValue)

  }

  });

  // 我们可以像使用一般的属性一样使用计算属性console.log ("The person's status is: ", person.status);

  让我们写一个简单的 defineComputed 函数,它支持调用计算方法,但目前不需要它支持 updateCallback 

  function defineComputed (obj, key, computeFunc, updateCallback) {

  Object.defineProperty (obj, key, {

  get: function () {

  // 执行计算函数并且返回值

  return computeFunc ();

  },

  set: function () {

  // 什么也不做,不需要设定计算属性的值

  }

  })

  }

  这个函数有两个问题:

  1. 每次访问计算属性时都会执行一次计算函数 computeFunc ()

  2. 它不知道什么时候更新 (即当我们更新某个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函数pushdeos

  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,

  'status',

  function () {

  if (person.age > 18) {

  return 'adult';

  }

  },

  function (newValue) {

  console.log ("status has changed to", newValue)

  }

  });

  console.log ("Status is ", person.status);

 

 

来源:网络


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值