vue,基于mvvm模式下的一个前端框架
mvvm模式下简单的实现数据代理,数据劫持
1.是用Object.defineProperty 实现数据代理
2.使用发布订阅者模式,配合 Object.defineProperty,实现数据劫持
数据劫持包括依赖收集和依赖促发
(只考虑最简单的方式,并且没有包括具体的依赖收集,我模拟的依赖收集,依赖收集得是在模板解析的时候,需要使用正则匹配出vue的一般指令和表达式)
/* 实现一个简易的vue */ class myvue { constructor (option) { let _self = this this._data = option.data this.proxydata(_self) /* 使用发布订阅者模式实现数据劫持 */ this.Datahijacking(_self) /* 实现一下模拟依赖收集 */ /* 本身模板解析时,会使用正则去匹配表达式和一般指令 匹配成功的表示是和一般指令都会调用以此数据劫持上的get方法 */ /* 假知我们传入的就是name 和 age */ this._data.name; this._data.name; this._data.name; this._data.age; this._data.age; /* 上面代表模板解析的时候一共调用的三次name 和 两次age */ } /* 实现vue对_data数据的代理 */ proxydata(_self) { /* 遍历传入的data的所有属性 */ Object.keys(_self._data).forEach(key=>{ Object.defineProperty(_self,key,{ configurable:true, enumerable: true, get () { return _self._data[key] }, set (val) { _self._data[key] = val } }) }) } /* 对_data数据劫持 */ Datahijacking(_self) { Object.keys(_self._data).forEach(key=>{ let value = _self._data[key] var dep = new Dep(); Object.defineProperty(_self._data,key,{ configurable:true, enumerable: true, get () { dep.addsubs(dep.id,new watch(key)) return value }, set (val) { dep.notify(val) } }) }) } } var uid = 0; class Dep { constructor () { this.id = uid++; this.handlers = [] } /* 依赖添加 */ addsubs (id,fn) { if(!this.handlers[id]) { this.handlers[id] = [] } this.handlers[id].push(fn) } /* 依赖促发 */ notify (val) { if(this.handlers) { this.handlers[this.id].forEach(fn=>{ fn.update(val); }) } } } /* 具体订阅者 */ class watch { constructor (name) { this.name = name } update (val) { /* 模拟试图更新 */ console.log('视图更新了'+val) } } let vm = new myvue({data:{ name: 'czklove', age: '17' }}) console.log(vm) vm.name = 'czklovel11'