/** * * 基本原理: * 1、通过Observer劫持data上的对象并监听data上的所有属性,遍历所有属性,并用Object.defineProperty转化为getter/setter,监听data上属性的的变化 * 2、将data上的属性挂载到vue的实例上,实例化后可以在vue使用this访问data属性 * 3、使用Compiler解析模板 * 4、Watcher:添加订阅者,访问和修改时update更新视图 * 5、Depend:addSub管理订阅数据对象,数据变化时notify通知所有数据对象进行视图更新 */ function myVue(options={}){ this.$options = options; this.$data = typeof this.$options == 'function' ? this.options.data() : this.$options.data; this.$el = this.$options.el; // 将this.$data添加到响应式系统 new Observer(this.$data) //将data上的属性添加到vue中 this.$proxy(); //解析模板 new Compiler(this.$el,this.$data); this.$options.created.call(this); } myVue.prototype.$proxy = function () { Object.keys(this.$data).forEach(key=>{ Object.defineProperty(this,key,{ configurable:true, enumerable:true, set(val){ this.$data[key] = val; }, get(){ return this.$data[key] } }); }) } // 响应式系统 function Observer($data){ Object.keys($data).forEach(key=>{ this.$ref($data,key,$data[key]) }) } Observer.prototype.$ref = function(_data,key,value){ let dep = new Depend(); Object.defineProperty(_data,key,{ configurable:true, enumerable:true, set(val){ if(value===val) return; value = val; dep.notify(); }, get(){ Depend.target && dep.addSub(Depend.target) return value } }) } // 依赖 function Depend(){ // 订阅者数组 this.subs = [] } // 添加订阅者 Depend.prototype.addSub = function(sub){ this.subs.push(sub) } Depend.prototype.notify = function(){ this.subs.forEach(sub=>{ sub.update(); }) } // 订阅者 function Watcher(node,name,data){ this.node = node; this.name = name; this.data = data; Depend.target = this; this.update(); Depend.target = null; } Watcher.prototype.update = function(){ if(this.node.nodeType===1){ this.node.value = this.data[this.name] } else if (this.node.nodeType === 3){ this.node.nodeValue = this.data[this.name] } } let reg = /\{\{(.+)\}\}/; // 解析模板 function Compiler(el,data){ this.el = document.querySelector(el); this.data = data; let frag = this.createFragment(); this.el.appendChild(frag); } Compiler.prototype.createFragment = function(){ let child; let frag = document.createDocumentFragment(); while(child = this.el.firstChild){ this._compiler(child); frag.appendChild(child); } return frag } Compiler.prototype._compiler = function(node){ // 标签节点 if(node.nodeType===1){ node.childNodes.forEach(item=>{ this._compiler(item); }) // 文本节点 }else if(node.nodeType===3){ if(reg.test(node.nodeValue)){ const name = reg.exec(node.nodeValue)[1] new Watcher(node,name,this.data) } } }
myVue标签:node,function,Depend,key,el,响应,vue2,原理,data From: https://www.cnblogs.com/jzm2842688813/p/18254707