关于computed
前言:
前言就是有了前几篇的基础对于vue相应式原理的初步了解之后,再去看这两个东西会方便很多。写这篇文章是为了一个梳理,还有一些其他的原因,年底再说。
先看computed
computed是在initState的时候,并且在初始化data之后,进行初始化的,来看看初始化的时候它干了什么:
function initComputed (vm, computed) {
// $flow-disable-line
var watchers = vm._computedWatchers = Object.create(null);
// computed properties are just getters during SSR
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
);
}
// component-defined computed properties are already defined on the
// component prototype. We only need to define computed properties defined
// at instantiation here.
if (!(key in vm)) {
defineComputed(vm, key, userDef);
} else {
if (key in vm.$data) {
warn(("The computed property \"" + key + "\" is already defined in data."), vm);
} else if (vm.$options.props && key in vm.$options.props) {
warn(("The computed property \"" + key + "\" is already defined as a prop."), vm);
}
}
}
}
两参数vm computed就是当前的vm组建和实例上的computed属性,说的通俗点就是new Vue的时候写的那个computed,然后我直接关注for in 里的代码:这里拿到computed上的key和对应的value之后,第一步是取得computed里key对应的value,这里value可能会是一个函数,一个对象,如果是函数就直接取,如果是对象就取他的get方法,然后会为当前的key生成一个watcher:
watchers[key] = new Watcher(
vm,
getter || noop,
noop,
computedWatcherOptions
);
//computedWatcherOptions 等于 var computedWatcherOptions = { lazy: true };
这里啊,这个lazy如果你对watcher构造函数的源码模糊了,建议重新打开一个窗口看看,computed从源码角度来讲,为什么data里的值变了之后才会跟着变呢,是因为这个地方,
第二步是判断当前key是否与props或data里边的key重复,有则警告,没有就调用defineComputed:
function defineComputed (
target,
key,
userDef
) {
var shouldCache = !isServerRendering();
if (typeof userDef === 'function') {
sharedPropertyDefinition.get = shouldCache
? createComputedGetter(key)
: createGetterInvoker(userDef);
sharedPropertyDefinition.set = noop;
} else {
sharedPropertyDefinition.get = userDef.get
? shouldCache && userDef.cache !== false
? createComputedGetter(key)
: createGetterInvoker(userDef.get)
: noop;
sharedPropertyDefinition.set = userDef.set || noop;
}
if (sharedPropertyDefinition.set === noop) {
sharedPropertyDefinition.set = function () {
warn(
("Computed property \"" + key + "\" was assigned to but it has no setter."),
this
);
};
}
Object.defineProperty(target, key, sharedPropertyDefinition);
}
//这里
var sharedPropertyDefinition = {
enumerable: true,
configurable: true,
get: noop,
set: noop
};
直接看最后一句,vue的老套路了,劫持一个对象的属性的get set,还有一层作用是执行vm.key的时候把这个操作代理到了当前定义的get上,其实computed的set不怎么常用,那来看看这里的get是什么:shouldChache是isServerRendering的执行结果取反的结果,isServerRendering 字如其名自然跟服务端渲染相关,看源码的话,当在服务端运行的时候此值才有可能取真值,那这里他就是false,然后,shouldChache自然取true,接着走,然后computed对应的value一般为function,所以这里执行createComputedGetter:
function createComputedGetter (key) {
return function computedGetter () {
var watcher = this._computedWatchers && this._computedWatchers[key];
if (watcher) {
if (watcher.dirty) {
watcher.evaluate();
}
if (Dep.target) {
watcher.depend();
}
return watcher.value
}
}
}
这里实际是把key闭了一个包,返回的函数呢,就是sharedPropertyDefinition的get,所以,此后某个地方访问vm.key的时候这个闭包函数就会执行,再看一下这个函数执行的细节,第一步取得当前computed里key对应的watcher实例,然后判断watcher.dirty是否为true,这个dirty和上边提到的lazy在实例化watcher的时候用的是同一个值,在初始化所有computed的时候他们都为true,因此第一次渲染的时候,这个地方会执行到watcher.evaluate():
Watcher.prototype.evaluate = function evaluate () {
this.value = this.get();
this.dirty = false;
};
evaluate很简单,计算value,标记dirty为false,这里的get前面我们也应该讲过:他做了一件事情就是将当前watcher pushTarget,然后调用watcher实例的getter方法,getter方法就是初始化watcher的时候传进去的那个getter,那这个getter里的东西呢,我们注意到computed里一般都会访问到当前data的get方法,而前几篇讲了在get方法中,我们就能收集到当前的watcher,因此此时就会完成依赖收集。然后computed就定义完毕了。
关于computed的更多相关文章
- mobx @computed的解读
写在前面:我一开始看不懂官网的@computed的作用,因为即使我把@computed去掉,依然能正确的report,然后我百度谷歌都找不到答案,下面都是我自己的理解,如果是有问题的,不对的,请务必留 ...
- vue中,class、内联style绑定、computed属性
1.绑定Class ①对象语法 <li :class="{ 'active': activeIdx==0 }" @click="fnClickTab(0)" ...
- redmine computed custom field formula tips
项目中要用到Computed custom field插件,公式不知道怎么写,查了些资料,记录在这里. 1.http://apidock.com/ruby/Time/strftime 查看ruby的字 ...
- Computed read-only property vs function in Swift
In the Introduction to Swift WWDC session, a read-only property description is demonstrated: class V ...
- 用computed返回this.$store.state.count,store更改了,但是computed没有调用
今天出现了这个问题,store更新了,你computed为啥不调用呢??? 另一个.vue更新了state,这个的computed就监听不到了么? 是用这种格式更新的this.$store.commi ...
- KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
Pure computed observables Pure computed observables是KO在3.2.0版本中推出的.她相对于之前的ComputedObservables有很多改进: ...
- knockout源码分析之computed(依赖属性)
一.序列图 二.主要代码文件 1.dependentObservable.js:主要包含ko.computed相关方法的处理2.dependencyDetection.js:主要包含依赖的监控上下文对 ...
- Knockout 新版应用开发教程之Computed Observables
Computed Observables 如果你有监控属性firstName和lastName的话,此时如果你想要显示全名? 这个时候computed(以前叫做依赖)监控属性就出马了,这是一个函数用来 ...
- Knockout 新版应用开发教程之Observable与computed
KO是什么? KO不是万能的,它的出现主要是为了方便的解决下面的问题: UI元素较多,用户交互比较频繁,需要编写大量的手工代码维护UI元素的状态.样式等属性? UI元素之间关系比较紧密,比如操作一个元 ...
- Vue.js学习 Item5 -- 计算属性computed与$watch
在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作.模板是为了描述视图的结构.在模板中放入太多的逻辑会让模板过重且难以维护.这就是为什么 Vue.js 将绑定表达式限制为一个表达式.如果需 ...
随机推荐
- Qt编写物联网管理平台40-类型种类
一.前言 为了增强本系统的拓展性,做成通用的物联网管理平台,特意将控制器主设备类型.探测器子设备类型.对应种类符号等信息,全部做成表格可自定义添加和修改,这样在控制器信息表和探测器信息表管理的时候,可 ...
- Qt数据库应用1-数据导入导出csv
一.前言 在经历过大大小小十几个甚至几十个纯QtWidget项目后,涉及到数据库相关的项目,几乎都有一个需求,将少量的信息数据比如设备信息.防区信息等,导出到文件保存好,然后用户可以打开该表格进行编辑 ...
- Qt通用方法及类库13
函数名 //设置按钮样式 static QString setPushButtonQss(QPushButton *btn, //按钮对象 int radius = 5, //圆角半径 int pad ...
- 使用 SK Plugin 给 LLM 添加能力
前几篇我们介绍了如何使用 SK + ollama 跟 LLM 进行基本的对话.如果只是对话的话其实不用什么 SK 也是可以的.今天让我们给 LLM 整点活,让它真的给我们干点啥. What is Pl ...
- Solution -「AGC 058D」Yet Another ABC String
\[\mathfrak{Defining~\LaTeX~macros\dots} \newcommand{\chr}[1]{\underline{\texttt{#1}}} \] \(\mathscr ...
- 「工具分享」Checker Script for Linux
以前整的一个 Linux 下对拍程序 qwq. 建一个文件夹, 假设叫 dir, 然后把 checker.sh 扔进去, 顺便 chmod +x checker.sh. 你需要自己设置一下代码 ...
- CDS标准视图:销售变现天数 I_DaysSalesOutstanding
视图名称:销售变现天数 I_DaysSalesOutstanding 视图类型:参数 视图代码: 点击查看代码 @AbapCatalog.sqlViewName: 'IFIDAYSSLSOUTSTG' ...
- runoob-PostgreSQL 教程
https://www.runoob.com/postgresql/postgresql-tutorial.html
- flink基础教程
随着大数据技术在各行各业的广泛应用,要求能对海量数据进行实时处理的需求越来越多,同时数据处理的业务逻辑也越来越复杂,传统的批处理方式和早期的流式处理框架也越来越难以在延迟性.吞吐量.容错能力以及使用便 ...
- Kubernetes 知识梳理及集群搭建
Kubernetes介绍 应用部署方式演变 在部署应用程序的方式上,主要经历了三个时代: 传统部署:互联网早期,会直接将应用程序部署在物理机上 优点:简单,不需要其它技术的参与 缺点:不能为应用程序定 ...