自己动手实现一个mvvm库
来源:互联网 发布:淘宝女装货源 编辑:程序博客网 时间:2024/05/18 01:17
一、总体大纲
要实现一个我们自己的mvvm库,我们首先需要做的事情不是写代码,而是整理一下思路,捋清楚之后再动手绝对会让你事半功倍。先上流程图,我们对着流程图来捋思路
如上图所示,我们可以看到,整体实现分为四步
- 实现一个
Observer
,对数据进行劫持,通知数据的变化 - 实现一个
Compile
,对指令进行解析,初始化视图,并且订阅数据的变更,绑定好更新函数 - 实现一个
Watcher
,将其作为以上两者的一个中介点,在接收数据变更的同时,让Dep
添加当前Watcher
,并及时通知视图进行update
- 实现
MVVM
,整合以上三者,作为一个入口函数
二、动手时间
思路捋清楚了,接下来要做的事就是开始动手。
能动手的我决不动口
1、实现Observer
这里我们需要做的事情就是实现数据劫持,并将数据变更给传递下去。那么这里将会用到的方法就是Object.defineProperty()
来做这么一件事。先不管三七二十一,咱先用用Object.defineProperty()
试试手感。
function observe (data) { if (!data || typeof data !== 'object') { return; } Object.keys(data).forEach(key => { observeProperty(data, key, data[key]) })}function observeProperty (obj, key, val) { observe(val); Object.defineProperty(obj, key, { enumerable: true, // 可枚举 configurable: true, // 可重新定义 get: function () { return val; }, set: function (newVal) { if (val === newVal || (newVal !== newVal && val !== val)) { return; } console.log('数据更新啦 ', val, '=>', newVal); val = newVal; } });}
调用
var data = { a: 'hello'}observe(data);
效果如下
看完是不是发现JavaScript
提供给我们的Object.defineProperty()
方法功能巨强大巨好用呢。
其实到这,我们已经算是完成了数据劫持,完整的Observer
则需要将数据的变更传递给Dep
实例,然后接下来的事情就丢给Dep
去通知下面完成接下来的事情了,完整代码如下所示
/** * @class 发布类 Observer that are attached to each observed * @param {[type]} value [vm参数] */ function observe(value, asRootData) { if (!value || typeof value !== 'object') { return; } return new Observer(value); }function Observer(value) { this.value = value; this.walk(value);}Observer.prototype = { walk: function (obj) { let self = this; Object.keys(obj).forEach(key => { self.observeProperty(obj, key, obj[key]); }); }, observeProperty: function (obj, key, val) { let dep = new Dep(); let childOb = observe(val); Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function() { if (Dep.target) { dep.depend(); } if (childOb) { childOb.dep.depend(); } return val; }, set: function(newVal) { if (val === newVal || (newVal !== newVal && val !== val)) { return; } val = newVal; // 监听子属性 childOb = observe(newVal); // 通知数据变更 dep.notify(); } }) }}/** * @class 依赖类 Dep */let uid = 0;function Dep() { // dep id this.id = uid++; // array 存储Watcher this.subs = [];}Dep.target = null;Dep.prototype = { /** * [添加订阅者] * @param {[Watcher]} sub [订阅者] */ addSub: function (sub) { this.subs.push(sub); }, /** * [移除订阅者] * @param {[Watcher]} sub [订阅者] */ removeSub: function (sub) { let index = this.subs.indexOf(sub); if (index !== -1) { this.subs.splice(index ,1); } }, // 通知数据变更 notify: function () { this.subs.forEach(sub => { // 执行sub的update更新函数 sub.update(); }); }, // add Watcher depend: function () { Dep.target.addDep(this); }}// 结合Watcher/*** Watcher.prototype = {* get: function () {* Dep.target = this;* let value = this.getter.call(this.vm, this.vm);* Dep.target = null;* return value;* },* addDep: function (dep) {* dep.addSub(this);* }* }*/
至此,我们已经实现了数据的劫持以及notify数据变化的功能了。
2、实现Compile
按理说我们应该紧接着实现Watcher
,毕竟从上面代码看来,Observer
和Watcher
关联好多啊,但是,我们在捋思路的时候也应该知道了,Watcher
和Compile
也是有一腿的哦。所以咱先把Compile
也给实现了,这样才能更好的让他们3P。
我不是老司机,我只是一个纯洁的开电动车的孩子
阅读全文
0 0
- 自己动手实现一个mvvm库
- 自己动手实现一个队列LGQueue
- 利用 JavaScript 数据绑定实现一个简单的 MVVM 库
- 实现一个类 Vue 的 MVVM 框架
- 230行实现一个简单的MVVM
- 自己动手实现一个简单的String类
- 自己动手实现一个简单的Ajax
- 自己动手实现一个《倒水解密》游戏
- 自己动手实现一个《倒水解密》游戏
- 自己动手实现一个《倒水解密》游戏
- 自己动手实现一个java过滤器类
- 自己动手实现一个C++智能指针
- 自己动手实现一个C#中List
- 自己动手实现一个队列LGQueue(刚刚)
- 自己动手实现一个简单c编译器
- 自己动手实现一个 Flex 布局框架
- 自己动手实现一个Android Studio插件
- 自己动手实现一个Android Studio插件
- VS2013+QT+OPENGL+Eigen+Cmake配置方法
- C#中Socket通信用法实例详解
- 分治法,贪心算法,动态规划算法总结(斯坦福算法课Algorithms:Design and Analysis Part2)
- [KMP fail树] BZOJ3670: [Noi2014]动物园
- Eclipse中创建新的Spring Boot项目
- 自己动手实现一个mvvm库
- Printf函数与Scanf函数学习
- 选择排序
- Hibernate4 命名查询
- 第七周 项目一 建立顺序环形队列
- 刘明春总结《2017年11月2号》【连续第6天总结】
- Hibernate
- C++语言细节点
- oracle单引号和双引号用法