我们来看看computed的实现。最简单的一个demo如下:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div id="app">
<div name="test">{{computeA}}</div> </div>
</body>
<script src="vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: function () {
return {
firstName: 111,
lastName: 222
}
},
computed: {
computeA: function () {
return this.firstName + ' ' + this.lastName
}
},
created(){
setTimeout(
() => {
this.firstName = 333;
},1000
)
}
})
</script>
</html>

  

1在初始化实例创建响应式的时候。对options中的computed做了特殊处理:

function initComputed (vm, computed) {
var watchers = vm._computedWatchers = Object.create(null); for (var key in computed) {
var userDef = computed[key];
var getter = typeof userDef === 'function' ? userDef : userDef.get;
{
if (getter === undefined) {
warn(
("No getter function has been defined for computed property \"" + key + "\"."),
vm
);
getter = noop;
}
}
// create internal watcher for the computed property.
watchers[key] = new Watcher(vm, getter, noop, computedWatcherOptions);//为每一个computed项目订制一个watcher // 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);
}
} function defineComputed (target, key, userDef) {
if (typeof userDef === 'function') {
sharedPropertyDefinition.get = createComputedGetter(key);
sharedPropertyDefinition.set = noop;
} else {
sharedPropertyDefinition.get = userDef.get
? userDef.cache !== false
? createComputedGetter(key)
: userDef.get
: noop;
sharedPropertyDefinition.set = userDef.set
? userDef.set
: noop;
}
Object.defineProperty(target, key, sharedPropertyDefinition);
} function createComputedGetter (key) {//构造该computed的get函数
return function computedGetter () {
var watcher = this._computedWatchers && this._computedWatchers[key];
if (watcher) {
if (watcher.dirty) {
watcher.evaluate();//收集该watcher的订阅
}
if (Dep.target) {
watcher.depend();//同一为这一组订阅再加上组件re-render的订阅(该订阅负责更新组件)
}
return watcher.value
}
}
}

  组件初始化的时候。computed项和data中的分别建立响应式。data中的数据直接对属性的get,set做数据拦截。而computed则建立一个新的watcher,在组件渲染的时候。先touch一下这个computed的getter函数。将这个watcher订阅起来。这里相当于这个computed的watcher订阅了firstname和lastname。touch完后。Dep.target此时又变为之前那个用于更新组件的。再通过watcher.depend()将这个组统一加上这个订阅。这样一旦firstname和lastname变了。同时会触发两个订阅更新。其中一个便是更新组件。重新re-render的函数。

vue computed 源码分析的更多相关文章

  1. Vue.js 源码分析(六) 基础篇 计算属性 computed 属性详解

    模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护,比如: <div id="example">{{ messag ...

  2. Vue.js 源码分析(四) 基础篇 响应式原理 data属性

    官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...

  3. Vue.js 源码分析(七) 基础篇 侦听器 watch属性详解

    先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的数据名,值为一个表达式(函数),还可以是一个对象, ...

  4. Vue.js 源码分析(十三) 基础篇 组件 props属性详解

    父组件通过props属性向子组件传递数据,定义组件的时候可以定义一个props属性,值可以是一个字符串数组或一个对象. 例如: <!DOCTYPE html> <html lang= ...

  5. Vue.js 源码分析(五) 基础篇 方法 methods属性详解

    methods中定义了Vue实例的方法,官网是这样介绍的: 例如:: <!DOCTYPE html> <html lang="en"> <head&g ...

  6. Vue.js 源码分析(三十二) 总结

    第一次写博客,坚持了一个多月时间,Vue源码分析基本分析完了,回过头也看也漏了一些地方,比如双向绑定里的观察者模式,也可以说是订阅者模式,也就是Vue里的Dep.Watcher等这些函数的作用,网上搜 ...

  7. Vue.js 源码分析(三十一) 高级应用 keep-alive 组件 详解

    当使用is特性切换不同的组件时,每次都会重新生成组件Vue实例并生成对应的VNode进行渲染,这样是比较花费性能的,而且切换重新显示时数据又会初始化,例如: <!DOCTYPE html> ...

  8. Vue.js 源码分析(三十) 高级应用 函数式组件 详解

    函数式组件比较特殊,也非常的灵活,它可以根据传入该组件的内容动态的渲染成任意想要的节点,在一些比较复杂的高级组件里用到,比如Vue-router里的<router-view>组件就是一个函 ...

  9. Vue.js 源码分析(二十九) 高级应用 transition-group组件 详解

    对于过度动画如果要同时渲染整个列表时,可以使用transition-group组件. transition-group组件的props和transition组件类似,不同点是transition-gr ...

随机推荐

  1. Python【外】第一节 map()和匿名函数的配合使用

    Python[外]第一节 map()和匿名函数的配合使用 map()函数 map函数使用语法如下:map(fun, iterable, ...) 功能: map() 会根据提供的函数fun对指定序列i ...

  2. spring基于注解的事务控制

    pom配置: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...

  3. kernel: possible SYN flooding on port 80. Sending cookies

    1. sysctl -w net.ipv4.tcp_syncookies=1 #启用使用syncookiessysctl -w net.ipv4.tcp_synack_retries=1 #降低syn ...

  4. C 编译器的“贪心法”

    C语言中有单字符符号和多字符符号之分,那么,当C编译器读入一个字符‘/’后又跟了一个字符‘*’,那么编译器就必须做出判断:是将其作为两个分别的符号对待,还是合起来作为一个符号对待.C语言对这个问题的解 ...

  5. 【Luogu】【关卡1-8】BOSS战-入门综合练习2(2017年10月)【AK】------都是基础题

    P1426 小鱼会有危险吗 我个人觉得这个题目出的不好,没说明白,就先只粘贴的AC代码吧 #include <bits/stdc++.h> using namespace std; int ...

  6. C#排序 转

    本文链接:https://blog.csdn.net/fysuccess/article/details/36416255 C#中List<T>排序的两种方法 List<Studen ...

  7. Makefile中的$(addprefix),添加前缀,指定目标生成目录

    先给大家看段Makefile的代码吧: INCLUDE_DIR=usr/java/jdk1..0_25/include \ usr/java/jdk1..0_25/include/linux INCL ...

  8. python基础特性之函数property

    函数property 1.为了保护属性,不让它随意的被更改(a.width=xxx)(起码,要符合某些条件),所以我们引入了set和get方法,虽然这个需要自定义(如下图的set_size,get_s ...

  9. Debug - SpringBoot - Error starting ApplicationContext. To display the auto-configuration report re-runyour application

    Error log 2019-12-07 22:33:03.959 ERROR 3760 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : ** ...

  10. Java网络爬虫笔记

    Java网络爬虫笔记 HttpClient来代替浏览器发起请求. select找到的是元素,也就是elements,你想要获取具体某一个属性的值,还是要用attr("")方法.标签 ...