computed vue 不 触发_Vue Computed 原理

本文探讨Vue中computed属性的工作原理,包括如何在实例化时处理computed对象,如何初始化并更新计算属性,以及其依赖跟踪和缓存机制。Vue通过Object.defineProperty的get/set方法实现数据响应,并利用Dep类进行订阅/发布模式,确保数据变更时仅重新计算必要的计算属性,从而提高性能。
摘要由CSDN通过智能技术生成

Computed 计算属性是 Vue 中常用的一个功能,在使用中发现他像是介于data和method之间的一个属性。他可以像是data一样在模板中{{message}}一样去使用,也可以通过this.message来调用;同时他也像method一样可以去处理数据逻辑。

本片文章就简要分析一下computed的原理,在此之间需要了解一下Vue数据响应的原理Object.defineProperty中的get/set重写。

原理解析

特殊处理computed

在Vue的实例化时,出入的对象中如果包含computed属性,构造内部会对这个对象进行特殊处理,处理成下一样的代码。

// 1.0实例化

var vm = new Vue({

data () {

return { }

}

computed: {

// key:value,

total: function _total() {

return this.a * this.b

}

},

})

// computed转化

var _computed = {

// computed的key值与原先同名,新的value是一个队原先value封装的函数

total: function(){

// 在实例上挂载响应的属性,这样就可以像data一样使用 this.total === vm.total

this.total = (function _total() {

return this.price * this.num

})()

}

}

computed初始化

初始化之后在vm上已经可以像data一样使用了

let target = null // target 是重点

// 遍历_computed

Object.keys(_computed).forEach(key = {

// 将key对应的function存入target中

target = computed[key] // [function]

// 执行target函数,函数内部更新了 vm[key] 的值

target()

// 清空target

target = null

})

监听和缓存

computed的基本特性是:

1、当data数据变更时,computed会更新

2、当computed中没有引入的数据更新时,computed不会去重新计算,大幅度节省计算量

实际是Vue内部创建了一个Dep类

get

在 computed初始化 中的代码可以看到,_computed在forEach的时候,target = _computed[key],也就是说,target执行的时候,如果内部触发get,那当前触发get属性的dep. depend函数中target函数中一定包含这个属性

例如触发在_computed.total中触发this.price的get时候,target === _computed.total ,dep. depend() 会将target 即 _computed.total 存入 price的subscribers中。

这样每个data中的属性都有一个自己的subscribers,其中是跟自己相关的computed函数

set

当触发set的时候,就回去遍历执行subscribers中的函数

如this.price = 100这样更新时,this.price中的subscribers = [_computed.total, ...],this.subscribers.forEach((sub)=>{sub()})就会更新相关的computed了

// 订阅/发布模式

class Dep {

constructor () {

// 调度中心 有几个computed引用到就有几个sub

this.subscribers = []

}

// 发布 get的时候调用

depend () {

if(target && !this.subscribers.includes(target)) { // target存在并且调度中心没有

this.subscribers.push(target) // 将target发布到调度中心

}

}

// 订阅

notify () {

// 便利调度中心 更新所有引用了这个数据的computed

this.subscribers.forEach((sub)=>{

sub()

})

}

}

Object.keys(data).forEach(key => {

let internalValue = null

const dep = new Dep() // 闭包的方式实现,每一个data中的属性都会有一个自己Dep实例

Object.defineProperty(data, key, {

get () {

dep.depend() // 当触发get的时候

return internalValue

}

set (newVal) {

internalValue = newVal

dep.notify() // 当触发set的时候

}

})

})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值