建议英文还可以的朋友直接读原版:skyronic.com/blog/vuejs-…,原文不难。如果有朋友觉得不好理解的话读我这篇也可以,我会在文中有些晦涩的地方加上自己的备注(用行内代码块表示)方便理解。这是我个人第一次翻译文章,如果有不对的地方还望指正,谢谢!

正文:

这篇文章,我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解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 '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 的值为 minorperson.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.targetDep.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);
复制代码

【翻译】Vue.js中的computed是如何工作的相关推荐

  1. 解析Vue.js中的computed工作原理

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

  2. vue.js中经典扫雷游戏的实现

    可视化 (vue-defuse) An implementation of the classical minesweeper game in vue.js. vue.js中经典扫雷游戏的实现. Vi ...

  3. echarts怎么用在php,在Vue.JS中怎样使用echarts

    这次给大家带来在Vue.JS中怎样使用echarts,在Vue.JS中使用echarts的注意事项有哪些,下面就是实战案例,一起来看一下. 上篇文章给大家介绍了 在 webpack 中使用 EChar ...

  4. Vue.js中的MVVM

    MVVM的理解 MVVM拆开来即为Model-View-ViewModel,有View,ViewModel,Model三部分组成.View层代表的是视图.模版,负责将数据模型转化为UI展现出来.Mod ...

  5. vue.js中mock本地json数据

    vue.js中mock本地json数据 新版本的vue项目中已经将dev-server.js,dev-client.js两个js文件合并到了webpack.dev.conf.js文件中,以下分别是新旧 ...

  6. VUE.js 中取得后台原生HTML字符串 原样显示问题

    今天使用vue调试页面,发现了页面上的一个问题,后台数据传过来的HTML字符串并没有被转换为正常的HTML代码,一拍脑门,发现忘记转换了,于是满心欢喜加上了{{{}}}.但是之后构建发现报错: 为此去 ...

  7. php动态写入vue,Vue.js中使用动态组件的方法

    本文介绍了如何在Vue.js中引用组件中的HTML元素.您可以通过使用Vue路由器或创建动态组件来切换视图或组件模板. Vue路由器用于在DOM中的视图或组件模板之间导航.要使用Vue路由器,请在ro ...

  8. 浅析Vue.js 中的条件渲染指令

    1 应用于单个元素 Vue.js 中的条件渲染指令可以根据表达式的值,来决定在 DOM 中是渲染还是销毁元素或组件. html: <div id="app"> < ...

  9. html5怎么改为vue_是否还在疑惑Vue.js中组件的data为什么是函数类型而不是对象类型...

    点击上方"前端印象",选择"设为星标"第一时间关注技术干货! 引言 要理解本篇文章,必须具备JavaScript中基本数据类型和引用数据类型的概念,大家可以花两 ...

最新文章

  1. rest-assured之Schema validation(包括JSON Schema validation及Xml Schema validation)
  2. 欢迎进入 K同学啊 的博客目录(全站式导航)
  3. boost::filesystem::detail::possible_large_file_size_support
  4. 远驱240控制器调整参数_PID控制中三个参数的作用
  5. ffmpeg 如何音视频同步
  6. MATLAB画图详细教程
  7. Deep Homography Estimation - Pytorch实现
  8. linux usb摄像头UVC usb3300 stm32F4
  9. php新年倒计时源码,新年倒计时源码
  10. 微信openid你了解多少?appid,appsecert又是啥?
  11. 用只读打开服务器上的文档,打开WebDAV文档在MS Office中以IT只读方式打开WebDAV服务器...
  12. 500. Keyboard Row
  13. 【Google Play】APK 扩展包 ( 2021年09月 最新处理方案 | 文件准备 | 拷贝文件至内置存储 | 解压及使用扩展文件 )
  14. asp实训报告摘要_asp实训报告总结.doc
  15. 车辆识别系统消息服务器异常,原来这样能处理好停车场车牌识别道闸一体机异常问题...
  16. 详解CSS中的display属性
  17. js截取空格之前的内容
  18. Boost 1.59.0 编译支持Python3的链接库,生成vc120或vc140
  19. 中国移动利润减少超过百亿,5G网络建设进度不如4G网络
  20. eclipse鼠标突然变成了黑色方块

热门文章

  1. Educational Codeforces Round 10 B. z-sort
  2. 保存画面为图片 当前MFC保存该程序为图片 c++ vc
  3. Ecipse:calculating requirements and dependencies(长时间阻塞问题)
  4. 数据结构笔记(十四)-- 串的模式匹配算法
  5. zynq中interrupts的学习笔记(一)
  6. mybatis事物如何避免脏读_新手指南:如何从java电商小白到秒杀大咖
  7. z17mini android 8,努比亚Z17mini和荣耀8哪个好?努比亚Z17mini与华为荣耀8全面区别对比评测...
  8. matlab保存数据用什么指令_Matlab数据处理——数据的保存和读取方法操作
  9. win10电脑桌面透明便签_Windows xp电脑便签在哪里找?XP系统怎么建桌面便签
  10. sigar-amd64-linux.so,sigar,no libsigar-amd64-linux.so in java.library.path