什么是双向绑定?
MVVM 作为数据绑定的入口:
Model 数据变化 -> View 视图更新
用户与 View 视图交互更新视图 -> 数据 Model 更新
双向绑定的原理
通过 Object.defineProperty() 数据劫持 各个属性的 setter 和 getter,结合 发布者-订阅者模式 的方式,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。
解释一下setter 和 getter:
在输出对象的属性时,控制台中对象的属性是由属性名 name
,值 key
,和其他特性(可读写性 writable
,可枚举性 enumerable
,可配置性 configurable
)组成的。
从ES5开始,提供了 getter
和 setter
可以将属性值的获取和设置分别绑定到方法上,称之为“ 存取器 ”。通过 getter 和 setter 能够在属性值的变更和获取时实现一些操作。ES6 新增的 class 改变了构造对象的书写方式,class中同样可以设置存取器。
如何实现双向绑定?
通过监听器 Observer、解析器 Compile、订阅者 Watcher 和 订阅器 Dep,以 MVVM 为数据绑定入口。
Watcher 作用:
① 在自身实例化时向属性订阅器(dep)添加 Watcher 实例
② 自身定义一个update()方法
③ 待属性变动 dep.notice() 通知时,调用自身的 update() 方法,同时触发 Compile 中绑定的回调
1.使用 Observer 对数据对象进行遍历(包括子属性对象的属性),利用Object.defineProperty() 在每个属性都加上 setter 和 getter。在对当前对象的某个值赋值时会触发 setter,从而监听数据变化。
2.使用 Compile 解析 Vue 模板指令,将模板中的变量都替换成数据,接着初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
3.每个组件实例都对应一个 Watcher 实例,Observer 和 Compile 之间通过 Watcher 通信,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
4.Dep 采用 发布-订阅 设计模式,用来收集 Watcher,对 Observer 和 Watcher 进行统一管理。
表单数据的双向绑定:v-model
两个操作:v-bind 绑定一个 value 属性,v-on 指令给当前元素绑定 input 事件
如果用户更新了 View,Model 的数据也自动更新
双向数据绑定 = 单向数据绑定 + DOM 事件监听