发布-订阅模式和观察者模式的区别
- 在观察者模式中,观察者是知道被观察者对象的,被观察者一直保持对观察者进行记录。
- 然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理(信息中介)进行通信,中介将订阅者和发布者串联起来,它过滤和分配所有输入的消息。
以下这幅图描绘了观察者和发布订阅两个模式的区别
Vue 2.x 双向数据绑定原理
-
首先,必须要有一个MVVM类,来作为数据的入口,它是一切的开始。
MVVM类,在Vue中,其实就是我们所说的Vue类,整个项目中只有一个new Vue()
这个类需要接收两个最基本的数据源(这里讲的是最简单的MVVM实现):$data, $elclass Vue { constructor (options) { this.$data = options.data; this.$el = document.querySelector(options.el); // ... } }
这样我们就明确了我们要监听和观察的对象:data, 我们要更新的视图:el
看图看图!先把这个数据绑定的实现分为两个部分看,一个是Observer劫持data,一个是Comilper解析el -
Obeserver劫持数据data
在Vue2.x版本中,劫持监控数据的原理是Object.defineProperty这个方法。很可惜的是,它做不到深度监听对象。
那么如何实现深度监听对象?
或许你听说过对象的深拷贝,实现深拷贝的方法是递归,所以我们劫持和监听data,也同样可以用递归来实现。// Observer /** * 监听data,劫持数据 * @param {*} data */ function observe (data) { if (Object.prototype.toString.call(data) === '[object Object]') { //确保监听的对象是object for (let prop in data) { defineReactive(data, prop, data[prop]); } } } /** * 对对象的key进行监听 * @param {*} obj * @param {*} key * @param {*} val */ function defineReactive (obj, key, val) { Reflect.defineProperty(obj, key, { //... }); observe(val);//递归监听对象的键值 } export default observe;
这里的Object.defineProperty,我替换成Reflect.defineProperty,效果是一样的,不明白Reflect的请复习一下ES6。
-
Compiler编译解析
视角转移到Compiler,它的作用是遍历dom,然后找到对应的指令,解析指令。
遍历dom的方式,也是递归:/** * 传入一个DOM树和数据源,DOM树上的节点会被遍历并编译 * @param {*} el * @param {*} scope */ function walkChildren