前言
本文章结合VUE核心技术-尚硅谷的56-62集做的归纳总结。
1.数据绑定(model==>View):
1). 一旦更新了data中的某个属性数据, 所有界面上直接使用或间接使用了此属性的节点都会更新(更新)
2.数据劫持
1). 数据劫持是vue中用来实现数据绑定的一种技术
2). 基本思想: 通过defineProperty()来监视data中所有属性(任意层次)数据的变化, 一旦变化就去更新界面
3.四个重要对象
1). Observer
* 用来对data所有属性数据进行劫持的构造函数
* 给data中所有属性重新定义属性描述(get/set)
* 为data中的每个属性创建对应的dep对象
2). Dep(Depend)
* data中的每个属性(所有层次)都对应一个dep对象
* 创建的时机:
* 在初始化define data中各个属性时创建对应的dep对象
* 在data中的某个属性值被设置为新的对象时
* 对象的结构
{
id, // 每个dep都有一个唯一的id
subs //包含n个对应watcher的数组(subscribes的简写)
}
* subs属性说明
* 当一个watcher被创建时, 内部会将当前watcher对象添加到对应的dep对象的subs中
* 当此data属性的值发生改变时, 所有subs中的watcher都会收到更新的通知, 从而最终更新对应的界面
3). Compile
* 用来解析模板页面的对象的构造函数(一个实例)
* 利用compile对象解析模板页面
* 每解析一个表达式(非事件指令)都会创建一个对应的watcher对象, 并建立watcher与dep的关系
* complie与watcher关系: 一对多的关系
4). Watcher
* 模板中每个非事件指令或表达式都对应一个watcher对象
* 监视当前表达式数据的变化
* 创建的时机: 在初始化编译模板时
* 对象的组成
{
vm, //vm对象
exp, //对应指令的表达式
cb, //当表达式所对应的数据发生改变的回调函数
value, //表达式当前的值
depIds //表达式中各级属性所对应的dep对象的集合对象
//属性名为dep的id, 属性值为dep
}
5). 总结: dep与watcher的关系: 多对多
* 一个data中的属性对应对应一个dep, 一个dep中可能包含多个watcher(模板中有几个表达式使用到了属性)
* 模板中一个非事件表达式对应一个watcher, 一个watcher中可能包含多个dep(表达式中包含了几个data属性)
* 数据绑定使用到2个核心技术
* defineProperty()
* 消息订阅与发布
4.双向数据绑定
1). 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的
2). 双向数据绑定的实现流程:
* 在解析v-model指令时, 给当前元素添加input监听
* 当input的value发生改变时, 将最新的值赋值给当前表达式所对应的data属性
数据绑定 model==>View
- 一旦更新了data中的某个属性数据, 所有界面上直接使用或间接使用了此属性的节点都会更新(更新)
数据劫持
- 数据劫持是vue中用来实现数据绑定的一种技术
- 基本思想: 通过defineProperty()来监视data中所有属性(任意层次)数据的变化, 一旦变化就去更新界面
四个重要对象
Observer
- 用来对data所有属性数据进行劫持的构造函数
- 给data中所有属性重新定义属性描述(get/set)
- 为data中的每个属性创建对应的dep对象
mvvm.js 内部会执行 observe 方法
observe 会创建 Observer 观察者实例
观察者内部会执行 walk 函数遍历数据
walk函数会遍历 data 中的数据,然后分别将data的键值对传入到 defineReactive 中
defineReactive 会再次对子元素的键值对对象调用 observe 方法,实现递归遍历所有子层级
遍历到的值会放到data中进行绑定
通过 get 和 set 方法来对数据进行监听和更新
Dep(Depend)
在上一节中也提到上面的代码执行,唯独跳过了 Watcher 的说明
这里就是用 Watcher 来监视数据变化,表达式exp对应的属性发生变化就执行更新方法
Watcher 内部会执行
this.get()
获取数据
在 get 中又用到了 Dep 对象
而 Dep 自身又 id 属性,每一次创建 id 都会 ++
里面有 subs 表示订阅者,可以实现监听。
subs 数组存放的是 Watcher 监听者
回到前面可以看到 Dep 实在 defineProperty 之前创建的,属于初始化的时候更新的
而Watcher是在 bind 方法中生成的,属于更新过程创建
每一组需要更新的元素会创建 watcher
dep则对依赖关系
双向数据绑定
编译指令属性到会去 编译 v-model 属性
compileUtil 中有 model 函数
model函数会执行bind方法
bind方法 会创建 Watcher 实现数据监听
接着获取 VM 数据
接着会添加事件监听器,通过 input 监听可以实现输入的触发
当 input 发生时,获取 input 的数据更新到变量当中
最后更新modelUpdater更新页面
1 | function Observer(data) { |
1 | function Watcher(vm, exp, cb) { |