数据绑定
“数据绑定”的关键在于监听数据的变化,可是对于这样一个对象:var obj = {value: 1},我们该怎么知道 obj 发生了改变呢?
Object.defineProperty
- ES5 提供了 Object.defineProperty 方法,该方法可以在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
- 语法:
Object.defineProperty(obj, prop, descriptor)
- 参数
- obj: 要在其上定义属性的对象
- prop: 要定义或修改的属性的名称
- descriptor: 将被定义或修改的属性的描述符
Proxy
- ES6提供了 Proxy,可以重定义更多的行为,比如 in、delete、函数调用等更多行为。
- Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
- 语法:
var proxy = new Proxy(target, handler)
- 复制代码proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。
- new Proxy()表示生成一个Proxy实例
- target参数表示所要拦截的目标对象
- handler参数也是一个对象,用来定制拦截行为
区别
使用Object.defineProperty的时候,我们遇到的问题有:
- 一次只能对一个属性进行监听,需要遍历来对所有属性监听
- 在遇到一个对象的属性还是一个对象的情况下,需要递归监听
- 对于对象的新增属性,需要手动监听
- 对于数组通过push、unshift方法增加的元素,也无法监听
Object.defineProperty简单实现
实现mvvm的双向绑定
是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。就必须要实现以下几点:
- 实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
- 实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
- 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
- mvvm入口函数,整合以上三者
具体实现