解析Vue.js中的computed工作原理小白知识_vue菜鸟教程网

我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的。写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下。JS属性:JavaScript有一个特性是 Object.defineProperty ,它能做很多事,但我在这篇文章只专注于这个方法中的一个:var person = {};
Obj

解析Vue.js中的computed工作原理小白知识

我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的。写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下。

解析Vue.js中的computed工作原理小白知识_vue菜鸟教程网

JS属性:

JavaScript有一个特性是 Object.defineProperty ,它能做很多事,但我在这篇文章只专注于这个方法中的一个:

var person = {};
Object.defineProperty (person, 'age', {
 get: function () {
  console.log ("Getting the age");
  return 25;
 }
});//欢迎加入前端全栈开发交流圈一起吹水聊天学习交流:864305860
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';
}//欢迎加入前端全栈开发交流圈一起吹水聊天学习交流:864305860
// 设置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 ();
  },//欢迎加入前端全栈开发交流圈一起吹水聊天学习交流:864305860
  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
 }//欢迎加入前端全栈开发交流圈一起吹水聊天学习交流:864305860
 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 ();
   });//欢迎加入前端全栈开发交流圈一起吹水聊天学习交流:864305860
  }//面向1-3年前端人员
 })
};

我们可以在计算属性定义的函数触发更新回调后更新 onDependencyUpdated 函数。

var onDependencyUpdated = function () {
 // 再次计算 计算属性的值
 var value = computeFunc ();
 updateCallback (value);
}//欢迎加入前端全栈开发交流圈一起学习交流:864305860

把它们整合到一起:
让我们重新访问我们的计算属性 person.status :

person.age = 22;
defineComputed (
 person,
 'status',
 function () {
  if (person.age > 18) {
   return 'adult';
  }
 },
 function (newValue) {
  console.log ("status has changed to", newValue)
 }//欢迎加入前端全栈开发交流圈一起学习交流:864305860
});
console.log ("Status is ", person.status);
海计划公众号
(0)
上一篇 2020/04/03 19:29
下一篇 2020/04/03 19:29

您可能感兴趣的内容

  • JavaScript 程序员可以从C教程视频中学到什么入门指南_语言

    如何通过了解类型、内存以及低级语言使你成为更好的程序员像许多开发新手一样,JavaScript 是我学的第一门语言。它是一种 Web 前端编程语言 —— 感谢Node.js —— 它同时也是一种流行的后端工具。我也相信,作为一种“更高级”的语言,JavaScript 是初学者的绝佳选择。你可以在任何 Web 浏览器上运行它,并且由于具有原型继承和动态类型等功

    2020/03/30
  • vue-i18n实现多语言切换效果基础指南_国际化指南攻略

    有些项目我们需要支持多种语言切换,满足国际化需求。 vue-i18n是一个vue插件,主要作用就是让项目支持国际化多语言,使用方便快捷,能很轻松的将我们的项目国际化。本文主要介绍使用vue-i18n实现切换中英文效果。 安装vue-i18n我们使用npm安装vue-i18n。npm install vue vue-i18n –save
    引入vue-i18

    2020/03/22
  • Dojo Build 简介菜鸟教程网_工具教程视频

    Dojo 提供了一套强大的命令行工具,让构建现代应用程序更加简单。可以自动创建包(Bundle),可以使用 PWA 在本地缓存文件,可以在构建阶段渲染初始的 HTML 和 CSS,也可以使用 Dojo 的 CLI 工具和.dojorc 配置文件按条件忽略一些代码。或者脱离(eject) Dojo 的构建工具,直接使用底层的构建工具以做到完全掌控。功能描述Do

    2020/03/23
  • hutool使用指南_一个Java基础工具类

    hutool使用指南 官方网址:http://www.hutool.cn GitHub:https://github.com/looly/hutool 简介描述:一个Java基础工…

    2020/03/06
  • 技术面试官的9大误区新手入门_面试使用帮助

    如果你做过技术面试官,就至少犯过下面9大误区中的一个:压制求职者拿自己擅长的东西问求职者寻找全才根据自己喜好评判求职者盲目相信求职者自己说得太多,让求职者说得太少不了解公司、团队、产品和岗位职责不清楚自己在面试中的角色和职责表现得对公司、团队、产品、技术等很失望接下来让我们一一来解释一下这些误区,并给出改善策略。1. 压制求职者有一些技术面试官,心里会有一个

    2020/04/03
  • 理解react生命周期菜鸟教程_周期使用帮助

    挂载(Mounting)挂载指的是组件被实例化并插入到dom中顺序如下:constructor -> getDerivedStateFromProps -> render -> componentDidMount更新(Updating)当state变化或者props变化会引起更新顺序如下:getDerivedStateFromProps -> shouldC

    2020/03/24
  • Sketch使用说明_Mac 上的 UI/UX 设计软件

    Sketch使用帮助 官方网址:https://sketchapp.com/ 简介描述:Mac 上的 UI/UX 设计软件 Sketch is a design toolkit b…

    2020/03/06
  • LABjs菜鸟教程_一个动态脚本加载器,异步加载组件

    LABjs菜鸟教程 官方网址:http://labjs.com GitHub:https://github.com/getify/LABjs 简介描述:一个动态脚本加载器,异步加载…

    2020/03/06
  • gridstack.js入门知识_一个用于块布局的 jQuery 插件

    gridstack.js入门知识 官方网址:http://gridstackjs.com/ GitHub:https://github.com/gridstack/gridstac…

    2020/03/06
  • docker搭建redis集群小白知识_redis小白常识

    1、 从docker库获取ruby镜像docker pull ruby2、创建虚拟网卡docker network create redis-net3、查看网卡信息docker network ls4、查看redis-net虚拟网卡网关ipdocker network inspect redis-net | grep “Gateway” | grep –c

    2020/03/26
  • 网页上常用的图片格式及使用场景菜鸟指南_图片入门基础

    1、jpg:有损压缩格式靠损失图片本身的质量来减小图片的体积,适用于颜色丰富的图像;(像素点组成的,像素点越多会越清晰 )2、gif:无损压缩格式靠损失图片的色彩数量来减小图片的体积,支持透明,支持动画,适用于颜色数量较少的图像;3、png:无损压缩格式损失图片的色彩数量来减小图片的体积,支持透明,不支持动画,是fireworks的 源文件格式,适用于颜色数

    2020/04/03
  • 精读《Nuxtjs》基础教程_nuxt小白知识

    1 引言Nuxt 是基于 Vue 的前端开发框架,这次我们通过 Introduction toNuxtJS 视频了解框架特色以及前端开发框架的基本要素。nuxt 与 next 结构很像,可以结合在一起看视频介绍了 NuxtJs 的安装、目录结构、页面路由、导航模版、asyncData、meta、vueX。这是一个入门级视频,所以上面所列举的特征都是一个前端开

    2020/03/23
  • 学习编程开发基础知识如何学习并掌握一门计算机编程语言_语言菜鸟攻略

    如果你有兴趣编写计算机程序,移动APP,网站,游戏或者任何软件,你应该学习编程。编程语言撰写的代码构建了计算机的程序。这个语言可以让程序让机器运行起来完成特写功能,机器指计算机、智能手机,其它任何的硬件产品中的一种。无论对于何种计算机编程语言,其核心编程思想都是一样的。算法以及解决问题的思想才是核心,编程只是一种实现算法及思想的工作。充分正确的认识这一点,对

    2020/04/03
  • 社交约会指南攻略正确的打开方式_约会零基础入门

    众所周知,纽约是世界上结婚率最低的城市。和国内情况完全不一样的是,这里的人自信程度比较高,甚至不只高一个级别,思想也是比较开放,勇于接受新的事物,并且相对来说比较独立。独立,这个东西,我分析过,一般体现在几个方面:首先,你是个情绪稳定的人,不会象个孩子一样情绪严重受外界影响。其次,你是个经济独立的人,你可以为自己喜欢的东西买单。最后,你是个善于主动去理解这个

    2020/03/22
  • 通过 41 个 问答方式快速了解学习 Git小白常识_git指南教程

    1. 你最喜欢的 Git 命令是什么个人比较喜欢 git add -p. 这增加了“补丁模式”的变化,这是一个内置的命令行程序。它遍历了每个更改,并要求确认是否要执行它们。这个命令迫使咱们放慢速度并检查更改文件。作为开发人员,咱们有时常常急于提交,我自己也经常这样,做完运行 git add . 才发现把调试的代码也提交上去了。2. 为什么你更喜欢直接使用 g

    2020/03/23
  • API接口设计,需要注意这4点基础知识教程_api入门基础

    原则上API接口设计一般出现在开发的详细设计中,但是随着诸多公司建立开放平台,产品经理也逐渐需要能理解API接口,尤其是做平台性的产品,还要学会定义接口。本文就关于产品经理在设计接口中需要定义什么、需要注意什么来展开陈述。看到人人都是产品经理社区已经有关于API接口的相关介绍,因此本文就不做过多的关于API接口概念方面的介绍。一、了解API的常识在做接口设计

    2020/03/22