如何使用proxy实现一个简单完整的MVVM库的示例代(2)

MVVM 模型中的核心,一般通过 Object.defineProperty 的 get,set 方法进行数据的监听,在 get 里添加订阅者,set 里通知订阅者更新视图。在本项目采用 Proxy 来实现数据监听,好处有三:

Proxy 可以直接监听对象而非属性

Proxy 可以直接监听数组的变化

Proxy 有多达 13 种拦截方法,

而劣势是兼容性问题,且无法通过 polyfill 磨平。查阅

注意 Proxy 只会监听自身的每一个属性,如果属性是对象,则该对象不会被监听,所以需要递归监听

设置监听后,返回一个 Proxy 替代原数据对象

var proxy = new Proxy(data, { get: function(target, key, receiver) { //如果满足条件则添加订阅者 dep.addDep(curWatcher); return Reflect.get(target, key, receiver); }, set: function(target, key, value, receiver) { //如果满足条件则通知订阅者 dep.notfiy(); return Reflect.set(target, key, value, receiver); } });

Watcher

在 Complier 模块里对每一个解析后的 Parser 进行指令与数据模型直接的绑定,并触发 Observer 的 get 监听,添加订阅者(Watcher)

this._getter(this.parser.dirValue)(this.scope || this.parser.cs.$data);

当数据模型变化时,就会触发 -> Observer 的 set 监听 -> Dep 的 notfiy 方法(通知订阅者的所有订阅列表) -> 执行订阅列表所有 Watcher 的 update 方法 -> 执行对应 Parser 的 update -> 完成更新视图

Watcher 里的 set 方法用于设置双向绑定值,注意访问层级

Dep

MVVM 的订阅中心,在这里收集数据模型的每个属性的订阅列表

包含添加订阅者,通知订阅者等方法

本质是一种发布/订阅模式

class Dep { constructor() { this.dependList = []; } addDep() { this.dependList.push(dep); } notfiy() { this.dependList.forEach(item => { item.update(); }); } }

后记

目前该 mvvm 项目只实现了数据绑定和视图更新的功能,通过这个简易轮子的实现,对 dom 操作,proxy,发布订阅模式等若干基础知识都进行了再次理解,查漏补缺。同时欢迎大家一起探讨交流,后面会继续完善!

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/7459e9cd52955c33e5221a8caaed5e5f.html