先来看看 Vue 的配置,以组件为例this
{ render(h) { }, props: { props1: Number }, data() { return { data1: 1, data2: 0 } }, computed: { computed1() { return this.data1 + this.props1 } }, watch: { computed1(newValue) { setTimeout(()=>{ console.log(newValue) },0) } } }
响应式实现过程大概能够分为三块:lua
初始化 data、props、computed 时(初始化 render 时还有一些其余内置属性),经过 Object.defineProperty
将属性定义成 get
和 set
,并为每一个属性绑定一个 Dep 实例。code
详见 src/core/instance/state.js
中 initData
和 initProps
。get
能够把整个 Vue 应用认为是大大小小的组件堆砌而成。Vue 为每一个组件都定义了两块重要的内容:Watcher 和 Render。it
执行 $mount
时调用 mountComponent
、初始化 watch、computed时、调用实例方法 $watch时,都会给实例化一个 Watcher。而 Watcher 初始化时会进行一次求值(执行实例中的 getter
方法),首先会将当前实例设置为 Dep 当前目标,而后触发数据的相关属性的 get
方法。console
详见 src/core/instance/state.js
中 initComputed
和 initWatch
。class
Dep
类就是用来关联数据与组件的 Watcher 的。响应式
// the current target watcher being evaluated. // this is globally unique because there could be only one // watcher being evaluated at any time. Dep.target = null
其实初始化 Watcher 时,经过执行了对应属性的 get
方法,将Watcher 实例放入数据对应的 Dep 实例的订阅列表中。而当数据发生变化时,对应属性执行 set
方法,会通知到对应的 Dep 实例,再通知订阅列表中的 Watcher。配置
此时,Watcher 将通知组件执行 Render,从新计算出新的 VNode,经过新旧 VNode 的对比,进行视图更新。方法