Computed 计算属性是 Vue 中常用的一个功能,我们今天来说一下他的执行过长

拿官网简单的例子来看一下:

<div id="example"><p>Original message: "{{ message }}"</p><p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>var vm = new Vue({el: '#example',data: {message: 'Hello'},computed: {// a computed getterreversedMessage: function () {// `this` points to the vm instancereturn this.message.split('').reverse().join('')}}
})

  

Vue 源码分析 Computed 的实现原理

data 属性初始化 getter setter:

// src/observer/index.js// 这里开始转换 data 的 getter setter,原始值已存入到 __ob__ 属性中
Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter () {const value = getter ? getter.call(obj) : val// 判断是否处于依赖收集状态if (Dep.target) {// 建立依赖关系
      dep.depend()...}return value},set: function reactiveSetter (newVal) {...// 依赖发生变化,通知到计算属性重新计算
    dep.notify()}
})

computed 计算属性初始化

// src/core/instance/state.js// 初始化计算属性
function initComputed (vm: Component, computed: Object) {...// 遍历 computed 计算属性for (const key in computed) {...// 创建 Watcher 实例// create internal watcher for the computed property.watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions)// 创建属性 vm.reversedMessage,并将提供的函数将用作属性 vm.reversedMessage 的 getter,// 最终 computed 与 data 会一起混合到 vm 下,所以当 computed 与 data 存在重名属性时会抛出警告
    defineComputed(vm, key, userDef)...}
}export function defineComputed (target: any, key: string, userDef: Object | Function) {...// 创建 get set 方法sharedPropertyDefinition.get = createComputedGetter(key)sharedPropertyDefinition.set = noop...// 创建属性 vm.reversedMessage,并初始化 getter setter
  Object.defineProperty(target, key, sharedPropertyDefinition)
}function createComputedGetter (key) {return function computedGetter () {const watcher = this._computedWatchers && this._computedWatchers[key]if (watcher) {if (watcher.dirty) {// watcher 暴露 evaluate 方法用于取值操作
        watcher.evaluate()}// 同第1步,判断是否处于依赖收集状态if (Dep.target) {watcher.depend()}return watcher.value}}
}

无论是属性还是计算属性,都会生成一个对应的 watcher 实例。

// src/core/observer/watcher.js// 当通过 vm.reversedMessage 获取计算属性时,就会进到这个 getter 方法
get () {// this 指的是 watcher 实例// 将当前 watcher 实例暂存到 Dep.target,这就表示开启了依赖收集任务pushTarget(this)let valueconst vm = this.vmtry {// 在执行 vm.reversedMessage 的函调函数时,会触发属性(步骤1)和计算属性(步骤2)的 getter// 在这个执行过程中,就可以收集到 vm.reversedMessage 的依赖了value = this.getter.call(vm, vm)} catch (e) {if (this.user) {handleError(e, vm, `getter for watcher "${this.expression}"`)} else {throw e}} finally {if (this.deep) {traverse(value)}// 结束依赖收集任务
    popTarget()this.cleanupDeps()}return value
}

上面多出提到了 dep.depend, dep.notify, Dep.target,那么 Dep 究竟是什么呢?

Dep 的代码短小精悍,但却承担着非常重要的依赖收集环节。

// src/core/observer/dep.js

export default class Dep {static target: ?Watcher;id: number;subs: Array<Watcher>;constructor () {this.id = uid++this.subs = []}addSub (sub: Watcher) {this.subs.push(sub)}removeSub (sub: Watcher) {remove(this.subs, sub)}depend () {if (Dep.target) {Dep.target.addDep(this)}}notify () {const subs = this.subs.slice()for (let i = 0, l = subs.length; i < l; i++) {// 更新 watcher 的值,与 watcher.evaluate() 类似,// 但 update 是给依赖变化时使用的,包含对 watch 的处理
      subs[i].update()}}
}// 当首次计算 computed 属性的值时,Dep 将会在计算期间对依赖进行收集
Dep.target = null
const targetStack = []export function pushTarget (_target: Watcher) {// 在一次依赖收集期间,如果有其他依赖收集任务开始(比如:当前 computed 计算属性嵌套其他 computed 计算属性),// 那么将会把当前 target 暂存到 targetStack,先进行其他 target 的依赖收集,if (Dep.target) targetStack.push(Dep.target)Dep.target = _target
}export function popTarget () {// 当嵌套的依赖收集任务完成后,将 target 恢复为上一层的 Watcher,并继续做依赖收集Dep.target = targetStack.pop()
}

总结

1. data 属性初始化 getter setter

2. computed 计算属性初始化,提供的函数将用作属性 vm.reversedMessage 的 getter

3. 当首次获取 reversedMessage 计算属性的值时,Dep 开始依赖收集

4. 在执行 message getter 方法时,如果 Dep 处于依赖收集状态,则判定 message 为 reversedMessage 的依赖,并建立依赖关系

5. 当 message 发生变化时,根据依赖关系,触发 reverseMessage 的重新计算

转载于:https://www.cnblogs.com/xuange306/p/9235131.html

深入理解 Vue Computed 计算属性相关推荐

  1. vue computed计算属性

    文章目录 前言 一.计算属性介绍 二.使用步骤 1.template中绑定计算属性 2.script中定义计算属性 3.计算属性的配置项 4.计算属性的简写 总结 前言 Vue中的计算属性(comup ...

  2. 理解Vue的计算属性

    计算属性是一个很邪门的东西,只要在它的函数里引用了 data 中的某个属性,当这个属性发生变化时,函数仿佛可以嗅探到这个变化,并自动重新执行. 上述代码会源源不断的打印出 b 的值.如果希望 a 依赖 ...

  3. computed计算属性

    今天主要介绍我所理解的computed计算属性 1.computed计算属性依赖于他的属性变化而变化 也就是依赖于data中的属性 只要依赖的data发生变化 就会触发调用一次计算属性 2.compu ...

  4. Vue中computed(计算属性)、methods、watch的区别

    初学vue,阅读api后,发现Vue提供了多种逻辑处理的方法,单纯的方法methods,computed(计算属性)以及watch等,充分理解这三者的区别,才能写出更加健壮的Vue代码. 1.meth ...

  5. 关于Vue中计算属性computed和methods属性的区别,你了解多少呢

    文章目录 1.实例 2.computed计算属性中: 前提1.当计算属性fn2没有依赖data中的数据时: 前提2.:当计算属性依赖data中的数据时: 3.区别: 在做项目过程中,有时会出现同一个需 ...

  6. vue的computed计算属性学习

    模板内的表达式是非常便利的,但是它们实际上只用于简单的运算.在模板中放入太多的逻辑会让模板过重且难以维护.这时候需要使用到vue的计算属性computed. 文件目录结构如下:利用vue脚手架创建 这 ...

  7. Vue的计算属性computed和监听属性watch

    Vue的计算属性computed 定义 通过已有属性计算生成一个新的组合属性. 原理 底层借助了Object.defineproperty方法提供的getter和setter来实现. 性质 计算属性的 ...

  8. Vue中的computed计算属性

    文章目录 computed与watch的异同 不同点 相同点 示例 源码 结果 分析 computed与watch的异同 不同点 触发条件不同   computed计算属性会依赖于使用它的data属性 ...

  9. Vue入门【三】-- 详解computed计算属性

    目录 computed: ♡ ‧₊˚ 基本使用 ‧₊˚ ♡ ♡ ‧₊˚语法‧₊˚ ♡ ♡ ‧₊˚效果‧₊˚ ♡ ♡ ‧₊˚ 面试问点 ‧₊˚ ♡ computed与methods的区别: comput ...

最新文章

  1. 全国青少年软件编程python等级考试-全国青少年软件编程等级考试:Python一级考试大纲...
  2. Apache Kafka-Spring Kafka生产消费@KafkaListener源码解析
  3. java setcharat,Java StringBuffer setCharAt()方法
  4. oracle sequrnce_OracleSql语句学习(五)
  5. 基于框架的应用系统的质量属性
  6. 《关于我的那些面经》——百度后端(附答案)
  7. KALI Linux中GURB安装失败如何处理
  8. linux升windows10,Windows 10免费升级计划的利与弊
  9. 学习之法 —— 如何阅读代码、如何编写代码
  10. 类型字节oracle 增强型时间类型以及postgresql时间类型
  11. python 日志输出变量_Python日志输出
  12. java session重复登录_Java开发网 - Hibernate:session中对象重复问题的解决方法(原创)...
  13. 【Yolov5】1.认真总结6000字Yolov5保姆级教程(2022.06.28全新版本v6.1)
  14. 海康8700联网网关如何通过GB28181接入安防摄像头互联网直播流媒体解决方案EasyGBS实现web端无插件直播
  15. 43张图详解计算机网络,看这一篇就够了
  16. OpenGL 简化点光源与平行光的对比实验
  17. BLE MESH中的Secure Network beacon包
  18. android一些可用实例2014收藏
  19. weblogic漏洞
  20. UUUUUUUUUUnity

热门文章

  1. CentOS 7 中firewall-cmd命令
  2. 黑马程序员--ADO.Net中的知识点和难点
  3. docker-ce安装
  4. Andorid Scrolling Activity(CoordinatorLayout详情)
  5. Redis3.2.5部署(单节点)
  6. 【USACO1.1】Broken Necklace
  7. PopupWindow在项目中的使用 并指定位置及加入动画效果
  8. The credentials you provided during SQL Server 2008 install are invalid
  9. pipenv相关指令
  10. Python html 代码转成 word(docx)