处理比较简单,只需要遍历 methods 配置的每个属性,将其对应的函数通过 bind 绑定到当前实例。之后复制其引用到组件实例即可(为了通过 this 可访问)。
// 伪代码
function Vue(options) {
// ...
// 其他代码
// ...
Object.entries(options.methods).forEach(([methodName, fn]) => {
this[methodName] = fn.bind(this);
});
}
new Vue(vnode.componentOptions);
在触发组件的生命周期函数 beforeCreate
后,会做一系列的事情,其中包括对 computed
的处理:
Watcher
对象,并传入一个函数。该函数本质上就是 computed 的 getter。之后 getter 触发时就会收集依赖。数据响应式中 Watcher 原理参考。
简单来说,为了监听响应式数据的变化来触发更新,Vue 会将使用了响应式数据的函数(模板对应render
函数)通过Watcher
记录下来(收集依赖)。之后响应式数据发生变化,就会通知对应的Watcher
来执行对应的函数触发更新。
Watcher
创建好之后,vue 会使用代理模式,将计算属性挂载到组件实例上(为了通过 this 访问)。
不同于渲染函数 render
的 Watcher
,为计算属性创建的 Watcher
不会立即执行。因为要考虑该计算属性是否被使用(渲染函数或其他方法中),没使用就不会执行。所以在创建 Watcher
时配置了一个 lazy
属性,lazy === true
时 Watcher
不会立即执行。
受到 lazy
的影响,Watcher
内部还会配置2个属性:value
和 dirty
Watcher
运行时的结果,一开始(Watcher
还没有执行时)为 undefined
。value
是否过期,一开始为 true
。当读取计算属性时,会先检查 dirty
,
true
时则运行之前传入 Watcher
的函数(也就是计算属性的 getter),将计算依赖得到的值保存在 Watcher
的 value
中,同时设置 dirty = false
。false
,则直接返回 Watcher.value
,也就是缓存的值。为了实现更新,在收集依赖时,被依赖的数据不仅会收集计算属性的 Watcher
,还会收集组件的 Watcher
。
当计算属性变化时,会先触发计算属性的 Watcher
,但只会将 dirty = true
,其他不做处理。之后触发组件的 Watcher
重新渲染。render
函数(或模板)又读取了计算属性,因为dirty === true
,所以会重新运行 getter 计算。
设置计算属性时比较简单,直接运行 setter
即可。
注意到上面触发更新时,如果计算属性的依赖发生变化,但计算属性没有在模板(或render
函数)中使用时(其他方法或watch场景同理),虽然会触发计算属性的 Watcher
,但不会触发同时收集到的组件的 Watcher
。
举例:
<template>
<div>
<h1 v-if="showName">{{ fullName }}</h1>
<button @click="handleClick">隐藏 fullName</button>
</div>
</template>
<script>
export default {
data() {
return {
firstName: '渣渣',
lastName: '辉',
showName: true
}
},
computed: {
fullName: {
get() {
return this.firstName + ' ' + this.lastName
},
set(newValue) {
;[this.firstName, this.lastName] = newValue.split(' ')
}
}
},
methods: {
handleClick() {
this.firstName = '123' // 计算属性依赖发生变化
this.showName = !this.showName
}
},
updated() {
console.log(this)
}
}
</script>
showName === false
所以不渲染 h1
,所以render
函数不会读取计算属性 fullName
。
所以只会执行:
计算属性的依赖:
firstName: [计算属性的 Watcher,组件的 Watcher(对应render函数 )]
lastName: [计算属性的 Watcher,组件的 Watcher(对应render函数)]
showName: [组件的 Watcher]
以上。