Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 141 题:Vue 中的 computed 是如何实现的 #291

Open
yygmind opened this issue Oct 15, 2019 · 10 comments
Open

第 141 题:Vue 中的 computed 是如何实现的 #291

yygmind opened this issue Oct 15, 2019 · 10 comments

Comments

@yygmind
Copy link
Contributor

yygmind commented Oct 15, 2019

No description provided.

@lizhongzhen11
Copy link

lizhongzhen11 commented Oct 15, 2019

之前的链接没用了,修改下新的链接:
https://ustbhuangyi.github.io/vue-analysis/v2/reactive/computed-watcher.html#computed

@HCLQ
Copy link

HCLQ commented Oct 16, 2019

实质是一个惰性的watcher,在取值操作时根据自身标记 dirty属性返回上一次计算结果/重新计算值
在创建时就进行一次取值操作,收集依赖变动的对象/属性(将自身压入dep中)
在依赖的对象/属性变动时,仅将自身标记dirty致为true

@xshinei
Copy link

xshinei commented Oct 24, 2019

computed本身是通过代理的方式代理到组件实例上的,所以读取计算属性的时候,执行的是一个内部的getter,而不是用户定义的方法。

computed内部实现了一个惰性的watcher,在实例化的时候不会去求值,其内部通过dirty属性标记计算属性是否需要重新求值。当computed依赖的任一状态(不一定是return中的)发生变化,都会通知这个惰性watcher,让它把dirty属性设置为true。所以,当再次读取这个计算属性的时候,就会重新去求值。

反对楼上说的,惰性watcher/计算属性在创建时是不会去求值的,是在使用的时候去求值的。

@HCLQ
Copy link

HCLQ commented Oct 24, 2019

computed本身是通过代理的方式代理到组件实例上的,所以读取计算属性的时候,执行的是一个内部的getter,而不是用户定义的方法。

computed内部实现了一个惰性的watcher,在实例化的时候不会去求值,其内部通过dirty属性标记计算属性是否需要重新求值。当computed依赖的任一状态(不一定是return中的)发生变化,都会通知这个惰性watcher,让它把dirty属性设置为true。所以,当再次读取这个计算属性的时候,就会重新去求值。

反对楼上说的,惰性watcher/计算属性在创建时是不会去求值的,是在使用的时候去求值的。

确实,更正一下

@hawtim
Copy link

hawtim commented Oct 24, 2019

@hbbaly
Copy link

hbbaly commented Oct 29, 2019

https://ustbhuangyi.github.io/vue-analysis/reactive/computed-watcher.html#computed

链接挂了

这本电子书改版了,所以之前的链接失效了,回到首页就可以看到了

@StrivingRabbit
Copy link

computed中的属性,通过代理,代理到vue的data上,对data进行处理的时候,已经添加了getter方法,然后当从vue实例上取该值的时候,将实例本身传递进computed函数内部,然后就可以拿到返回值了。
所以函数内部有值改变的时候,触发watcher,computed也会跟着重新计算

@yygmind yygmind added the Vue label Dec 16, 2019
@Wowoy
Copy link

Wowoy commented Dec 17, 2019

在initComputed中遍历每一个computed属性,创建对应的Watcher。在Watcher实例化过程中,计算computed属性结果,会对依赖的data进行取值,从而触发data的getter进行依赖收集,将当前Watcher加入到订阅者数组中。当computed属性依赖的data改变时,会触发data的setter通知订阅者更新,这个computed会重新计算。

@m7yue
Copy link

m7yue commented Sep 24, 2020

初始化阶段:
创建每一个计算属性对应的 watcher , dirty 为true, 将计算属性定义到实例上, 就可通过this.xxx 获取。
同时会对计算方法做一层包装:根据 dirty 判断是执行方法还是返回缓存值 (watcher.value)

第一次获取计算属性值:

  1. 会执行 watcher 的 evaluate 方法 , 这个 evalute 就是执行了计算方法 然后更新 watcher 的 value。并且设置了dirty 为 false
  2. 重点: 在执行计算方法的时候, 会触发每一个依赖的响应数据的 get 而此时 Dep.target 就是当前计算属性对应的watcher
  3.   依赖的相应数据 会 将当前的watcher 放入自己管理的订阅器中(依赖收集)。
  4. 这样当某个依赖的相应数据变更的时候,触发订阅器发布更新,会执行上面watcher 的 update方法,这个update方法知道这是个计算属性的watcher 就干了一件事, 把dirty 设为 true

第二次获取计算属性值:
  如果依赖的相应数据又变更,那么 watcher.dirty=true,会执行计算方法获取新值,否则获取到缓存的 watcher.value。

@renbinghao
Copy link

所以computed的缓存是什么原因呢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants