深入理解 Vue Computed 计算属性
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 计算属性相关推荐
- vue computed计算属性
文章目录 前言 一.计算属性介绍 二.使用步骤 1.template中绑定计算属性 2.script中定义计算属性 3.计算属性的配置项 4.计算属性的简写 总结 前言 Vue中的计算属性(comup ...
- 理解Vue的计算属性
计算属性是一个很邪门的东西,只要在它的函数里引用了 data 中的某个属性,当这个属性发生变化时,函数仿佛可以嗅探到这个变化,并自动重新执行. 上述代码会源源不断的打印出 b 的值.如果希望 a 依赖 ...
- computed计算属性
今天主要介绍我所理解的computed计算属性 1.computed计算属性依赖于他的属性变化而变化 也就是依赖于data中的属性 只要依赖的data发生变化 就会触发调用一次计算属性 2.compu ...
- Vue中computed(计算属性)、methods、watch的区别
初学vue,阅读api后,发现Vue提供了多种逻辑处理的方法,单纯的方法methods,computed(计算属性)以及watch等,充分理解这三者的区别,才能写出更加健壮的Vue代码. 1.meth ...
- 关于Vue中计算属性computed和methods属性的区别,你了解多少呢
文章目录 1.实例 2.computed计算属性中: 前提1.当计算属性fn2没有依赖data中的数据时: 前提2.:当计算属性依赖data中的数据时: 3.区别: 在做项目过程中,有时会出现同一个需 ...
- vue的computed计算属性学习
模板内的表达式是非常便利的,但是它们实际上只用于简单的运算.在模板中放入太多的逻辑会让模板过重且难以维护.这时候需要使用到vue的计算属性computed. 文件目录结构如下:利用vue脚手架创建 这 ...
- Vue的计算属性computed和监听属性watch
Vue的计算属性computed 定义 通过已有属性计算生成一个新的组合属性. 原理 底层借助了Object.defineproperty方法提供的getter和setter来实现. 性质 计算属性的 ...
- Vue中的computed计算属性
文章目录 computed与watch的异同 不同点 相同点 示例 源码 结果 分析 computed与watch的异同 不同点 触发条件不同 computed计算属性会依赖于使用它的data属性 ...
- Vue入门【三】-- 详解computed计算属性
目录 computed: ♡ ‧₊˚ 基本使用 ‧₊˚ ♡ ♡ ‧₊˚语法‧₊˚ ♡ ♡ ‧₊˚效果‧₊˚ ♡ ♡ ‧₊˚ 面试问点 ‧₊˚ ♡ computed与methods的区别: comput ...
最新文章
- 全国青少年软件编程python等级考试-全国青少年软件编程等级考试:Python一级考试大纲...
- Apache Kafka-Spring Kafka生产消费@KafkaListener源码解析
- java setcharat,Java StringBuffer setCharAt()方法
- oracle sequrnce_OracleSql语句学习(五)
- 基于框架的应用系统的质量属性
- 《关于我的那些面经》——百度后端(附答案)
- KALI Linux中GURB安装失败如何处理
- linux升windows10,Windows 10免费升级计划的利与弊
- 学习之法 —— 如何阅读代码、如何编写代码
- 类型字节oracle 增强型时间类型以及postgresql时间类型
- python 日志输出变量_Python日志输出
- java session重复登录_Java开发网 - Hibernate:session中对象重复问题的解决方法(原创)...
- 【Yolov5】1.认真总结6000字Yolov5保姆级教程(2022.06.28全新版本v6.1)
- 海康8700联网网关如何通过GB28181接入安防摄像头互联网直播流媒体解决方案EasyGBS实现web端无插件直播
- 43张图详解计算机网络,看这一篇就够了
- OpenGL 简化点光源与平行光的对比实验
- BLE MESH中的Secure Network beacon包
- android一些可用实例2014收藏
- weblogic漏洞
- UUUUUUUUUUnity
热门文章
- CentOS 7 中firewall-cmd命令
- 黑马程序员--ADO.Net中的知识点和难点
- docker-ce安装
- Andorid Scrolling Activity(CoordinatorLayout详情)
- Redis3.2.5部署(单节点)
- 【USACO1.1】Broken Necklace
- PopupWindow在项目中的使用 并指定位置及加入动画效果
- The credentials you provided during SQL Server 2008 install are invalid
- pipenv相关指令
- Python html 代码转成 word(docx)