数据驱动
- 数据响应式、双向绑定、数据驱动
- 数据响应式
- 数据模型仅仅是普通的
JavaScript对象,而当我们修改数据时,视图会进行更新,避免了繁琐的DOM操作提高开发效率
- 数据模型仅仅是普通的
- 双向绑定
- 数据改变,视图改变;视图改变,数据也随之改变
- 我们可以使用
v-model在表单元素上创建双向数据绑定
- 数据驱动是
Vue最独特的特性之一- 开发过程中仅需要关注数据本身,不需要关心数据是如何渲染到视图
数据响应式的核心原理
Vue 2.x
- Vue 2.x深入响应式原理
- MDN - Object.defineProperty
- 浏览器兼容 IE8 以上(不兼容 IE8)
// 模拟 Vue 中的 data 选项 |
如果有一个对象中多个属性需要转换
getter/setter如何处理?
Vue 3.x
- MDN - Proxy
- 直接监听对象,而非属性
ES 6中新增,IE不支持,性能由浏览器优化
// 模拟 Vue 中的 data 选项 |
发布订阅模式和观察者模式
发布/订阅模式
- 发布/订阅模式
- 订阅者
- 发布者
- 信号中心
我们假定,存在一个”信号中心”,某个任务执行完成,就向信号中心”发布”(publish)一个信 号,其他任务可以向信号中心”订阅”(subscribe)这个信号,从而知道什么时候自己可以开始执 行。这就叫做”发布/订阅模式”(publish-subscribe pattern)
Vue 的自定义事件
let vm = new Vue() |
兄弟组件通信过程
// eventBus.js |
模拟 Vue 自定义事件的实现
class EventEmitter { |
观察者模式
- 观察者(订阅者) –
Watcherupdate():当事件发生时,具体要做的事情
- 目标(发布者) –
Depsubs数组:存储所有的观察者addSub():添加观察者notify():当事件发生,调用所有观察者的update()方法
- 没有事件中心
// 目标(发布者) |
总结
- 观察者模式是由具体目标调度,比如当事件触发,
Dep就会去调用观察者的方法,所以观察者模
式的订阅者与发布者之间是存在依赖的 - 发布/订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在

Vue 响应式原理模拟
整体分析
- Vue 基本结构
- 打印 Vue 实例观察
- 整体结构

Vue: 把data中的成员注入到Vue实例,并且把data中的成员转成getter/setterObserver:能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知DepCompiler:解析每个元素中的指令/插值表达式,并替换成相应的数据Dep:添加观察者(watcher),当数据变化通知所有观察者Watcher:数据变化更新视图
Vue
- 功能
- 负责接收初始化的参数(选项)
- 负责把
data中的属性注入到Vue实例,转换成getter/setter - 负责调用
observer监听data中所有属性的变化 - 负责调用
compiler解析指令/插值表达式
- 结构

class Vue { |
Observer
- 功能
- 负责把
data选项中的属性转换成响应式数据 data中的某个属性也是对象,把该属性转换成响应式数据- 数据变化发送通知
- 负责把
- 结构

// 负责数据劫持 |
Compiler
- 功能
- 负责编译模板,解析指令/插值表达式
- 负责页面的首次渲染
- 当数据变化后重新渲染视图
- 结构

1. compile()
// 负责解析指令/插值表达式 |
2. compileText()
- 负责编译插值表达式
// 编译文本节点 |
3. compileElement()
- 负责编译元素的指令
- 处理
v-text的首次渲染 - 处理
v-model的首次渲染
// 编译属性节点 |
Dep(Dependency)

- 功能
- 收集依赖,添加观察者(
watcher) - 通知所有观察者
- 收集依赖,添加观察者(
- 结构

class Dep { |
在
compiler.js中收集依赖,发送通知
// defineReactive 中 |
Watcher

- 功能
- 当数据变化触发依赖,
dep通知所有的Watcher实例更新视图 - 自身实例化的时候往
dep对象中添加自己
-结构
- 当数据变化触发依赖,

class Watcher { |
在
compiler.js中为每一个指令/插值表达式创建watcher对象,监视数据的变化
// 因为在 textUpdater等中要使用 this |
视图变化更新数据
// v-model 指令的更新方法 |
总结
通过下图回顾整体流程

- Vue
- 记录传入的选项,设置
$data/$el - 把
data的成员注入到Vue实例 - 负责调用
Observer实现数据响应式处理(数据劫持) - 负责调用
Compiler编译指令/插值表达式等
- 记录传入的选项,设置
Observer- 数据劫持
- 负责把
data中的成员转换成getter/setter - 负责把多层属性转换成
getter/setter - 如果给属性赋值为新对象,把新对象的成员设置为
getter/setter
- 负责把
- 添加
Dep和Watcher的依赖关系 - 数据变化发送通知
- 数据劫持
Compiler- 负责编译模板,解析指令/插值表达式
- 负责页面的首次渲染过程
- 当数据变化后重新渲染
Dep- 收集依赖,添加订阅者(
watcher) - 通知所有订阅者
- 收集依赖,添加订阅者(
Watcher- 自身实例化的时候往
dep对象中添加自己 - 当数据变化
dep通知所有的Watcher实例更新视图
- 自身实例化的时候往