前言
今天来研究下Vue中的 Computed源码过程,学习computed我们必须理解一下几点:
我们知道vue调用实例后,Vue内部initState时候,会处理很多不同的数据,包括有data、props、methods....
处理computed的方法就是initComputed。 看看initComputed做了些啥!
function initComputed(vm, computed) {
var watchers = vm._computedWatchers = Object.create(null);
// 是否服务器渲染
var isSSR = isServerRendering();
for (var key in computed) {
var userDef = computed[key];
var getter = typeof userDef === 'function' ? userDef : userDef.get;
if (getter == null) {
warn(
("Getter is missing for computed property \"" + key + "\"."),
vm
);
}
if (!isSSR) {
// create internal watcher for the computed property.
watchers[key] = new Watcher(
vm,
getter || noop,
noop,
computedWatcherOptions
);
}
if (!(key in vm)) {
defineComputed(vm, key, userDef);
}
}
}
上面做了几件事1.为每个computed中的属性添加 watcher。2.defineComputed的处理
1.new Watcher生成一个computed-Watcher
先来看下new Watcher()做了些啥,先列出重点的源码
function Watcher(vm, expOrFn, options) {
this.dirty = this.lazy = options.lazy;
this.getter = expOrFn;
this.value = this.lazy ? undefined: this.get();
};
// getter 就是 watcher 回调
Watcher.prototype.get = function() {
var value = this.getter.call(vm, vm);
return value
};
一开始new Watcher(vm, getter, { lazy: true })
的lazy
是设为true,这样在执行computed中属性初始化的时候,不用立马求值,算是一个小优化吧!只有等到后面再次请求computed中的值才会进行this.get();
2.再看看defineComputed做了一些什么鬼!
function defineComputed(
target, key, userDef
) {
// 设置 set 为默认值,避免 computed 并没有设置 set
var set = function(){}
// 如果用户设置了set,就使用用户的set
Object.defineProperty(target, key, {
// 包装get 函数,主要用于判断计算缓存结果是否有效
get:createComputedGetter(key),
set:set
});
}
其实就是给computed中的每一个属性都进行依赖拦截处理,看下get中重点createComputedGetter。
function createComputedGetter(key) {
return function() {
// 获取到相应 key 的 computed-watcher
var watcher = this._computedWatchers[key];
// 如果 computed 依赖的数据变化,dirty 会变成true,从而重新计算,然后更新缓存值 watcher.value
if (watcher.dirty) {
watcher.evaluate();
}
// 这里后面重点讲,主要是建立联系
if (Dep.target) {
watcher.depend();
}
return watcher.value
}
Watcher.prototype.evaluate = function() {
this.value = this.get();
this.dirty = false;
};
看到上面的watcher.dirty
了吗,就是这个,当你dirty为true时才会执行内部的watcher.evaluate()
,执行之后又会进行this.dirty
进行设为false,这样就不用每一次都进行重新求值,起到了真正缓存的作用,那什么时候才要进行设为dirty为true呢,就是比如说当computed依赖的响应数据进行变化的时候,会触发它依赖收集中的computed-watcher
,之后进行update。看下面简单源码
Watcher.prototype.update = function() {
if (this.lazy) this.dirty = true;
....还有其他无关操作,已被省略
};
这样在你只要重新获取computed中的属性值就会执行get,从而执行watcher.evaluate()。
重点是上面的watcher的depend(),后续再讲!累了
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!