- MVVM
Model(数据模型)——ViewModel——View(UI组件)
数据绑定到ViewModel并自动渲染至页面View,视图变化时通知viewModel层更新Model数据
一、Vue2.x双向绑定原理
-
Vue双向绑定:数据变化更新视图,视图变化更新数据
-
视图变化更新数据:
事件监听
-
数据变化更新视图:
1.一个普通的js对象传入vue实例作为data属性,vue遍历此对象所有的property
,并使用Object.defineProperty
把这些property
全部转为 getter/setter
2.getter/setter 对用户不可见,但在内部可以让vue追踪依赖,在property被访问和修改时通知变更
3.每一个组件实例对应一个watcher
实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。 -
监听器 Observer:对数据对象进行遍历,利用
Object.defineProperty
对数据对象属性都加上setter
和getter
,数据变化就会触发setter
,此时就能监听到数据变化 -
解析器 Compile:解析Vue模板指令,将模板中的变量都换成数据,然后初始化渲染页面,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据变动,调用更新函数进行数据更新
-
订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 。当订阅者收到Observer中的属性值变化时,触发解析器Compile中对应的更新函数。
**观察者模式:**每个组件实例
都有相应的 watcher 实例对象
,它会在组件渲染的过程中把属性
记录为依赖
,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新
二、Vue3.x响应式数据
-
Vue3.x改用Proxy替代Object.defineProperty。
-
Proxy可以直接监听对象和数组的变化,并有多种拦截方法
-
问题:Proxy只会代理对象的第一层,
- 判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理, 这样就实现了深度观测。 - 监测数组的时候可能触发多次get/set,那么如何防止触发多次呢?我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger。