首页 > 语言 > JavaScript > 正文

深入理解Vue Computed计算属性原理

2024-05-06 15:33:48
字体:
来源:转载
供稿:网友

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 getter  reversedMessage: function () {   // `this` points to the vm instance   return this.message.split('').reverse().join('')  } }})

Situation

Vue 里的 Computed 属性非常频繁的被使用到,但并不是很清楚它的实现原理。比如:计算属性如何与属性建立依赖关系?属性发生变化又如何通知到计算属性重新计算?

关于如何建立依赖关系,我的第一个想到的就是语法解析,但这样太浪费性能,因此排除,第二个想到的就是利用 JavaScript 单线程的原理和 Vue 的 Getter 设计,通过一个简单的发布订阅,就可以在一次计算属性求值的过程中收集到相关依赖。

因此接下来的任务就是从 Vue 源码一步步分析 Computed 的实现原理。

Task

分析依赖收集实现原理,分析动态计算实现原理。

Action

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  } }}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选