Vue.js中的computed工作原理_深入理解 Vue的Computed计算属性

更新日期: 2018-09-13阅读量: 3090标签: Vue

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 '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 () {
   // 什么也不做,不需要设定计算属性的值
  }
 })
}


这个函数有两个问题:

每次访问计算属性时都会执行一次计算函数 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,
 'status',
 function () {
  if (person.age > 18) {
   return 'adult';
  }
 },
 function (newValue) {
  console.log ("status has changed to", newValue)
 }
});
console.log ("Status is ", person.status);


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: https://www.fly63.com/article/detial/1080

从 Vue parseHTML 来学习正则表达式

写作本文的起源在于,在分析 Vue 源码中 parseHTML 方法时,发现网上对其中正则的解析文章较少,找到的几篇文章也有些语焉不详。于是静下心逐个表达式分析了其中的正则,以备查看。

vue之nextTick全面解析

vue是非常流行的框架,他结合了angular和react的优点,从而形成了一个轻量级的易上手的具有双向数据绑定特性的mvvm框架。本人比较喜欢用之。在我们用vue时,我们经常用到一个方法是this.$nextTick

如何理解Vue.js中的ref及$ref,$

首先我们来看一下vue官方是怎么解释的m好了,我知道很多刚接触的vue的小白其实都不太看的懂官方文档在讲什么,下面我用自己的话翻译一下。

Vue 3.0 将从头开始重写!

Vue.js 伦敦大会上,Vue.js 作者尤雨溪简要介绍了 Vue 下一个主要版本要发布的内容,不久前,尤雨溪在 medium 个人博客上发布了 Vue 3.0 的开发路线,我们不妨看看 Vue 3.0 将会有怎样的发展。

Vue最佳实践

Vue 最佳实践,是参考 Vue 官方风格指南并根据过去 Vue 实际项目开发中的经验总结的一套规范建议。本项目的目的是希望每个 Vue 开发者都能尽快熟悉并上手项目代码,志在帮助 Vue 新手开发者及时避免一些不规范的设计和由此而引发的问题

Vue中mixin怎么理解?

mixin是为了让可复用的功能灵活的混入到当前组件中,混合的对象可以包含任意组件选项(生命周期,指令之类等等), mixin翻译过来叫混合,高级的词汇可以叫插件入侵

vue2.0/3.0在main.js引入scss文件报错

在vue2.0的main.js中引入scss文件报错原因是:在build文件夹下的webpack.base.conf.js的rules里面添加配置,vue3.0写入.scss文件在mian.js中 import ‘./styles/index.scss‘后出现下图报错解决方法:在vue.config.js文件中添加以下代码

你应该知道的Vue高级特性

Vue为我们提供了很多高级特性,学习和掌握它们有助于提高你的代码水平。从我们刚开始学习Vue的时候,对于侦听属性,都是简单地如下面一般使用:

vue介绍

库是一种插件,是一种封装好的特定方法的集合。提供给开发者使用,控制器在使用者手里。框架是一套架构,会基于自身特定向用户提供一套相当完整的解决方案,控制权在框架本身

vue 自定义指令

接下来我们来看一下钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。但有一些是没有相对应的指令进行操作。在这里以progress(h5的新标签进度条)为例,向大家介绍Vue的一个用于指令扩展的方法:directive(自定义指令)。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!