MVVM具体含义 M:model(服务端逻辑) v:view vm(viewModel 特指vue.js,react.js处理服务和视图层的逻辑) 和MVC的区别:页面与逻辑完全分离,可双向绑定
双向绑定原理 data - > watcher ->更新 view
Object.defineProperty(obj,prop,descripor) obj:对象 prop:要修改的属性 descripor:定义或者修改的属性的描述 会直接在一个对象上定义一个新属性或对已有的属性修改,然后返回这个对象 比如vue 的data就是一个对象,所以可以对里边定义的属性进行双向绑定
双向绑定设计模式 data => observer(Object.defineProperty) => watcher => view
实现一个简单的双向绑定 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <input id="objInput" type="" name=""> <div id="area"></div> var obj = {} Object.defineProperty(obj,'a',{ get:function(){ return val }, set:function(val){ document.getElementById('objInput').value = val document.getElementById('area').innerHTML = val } }) document.addEventListener('keyup',function(e){ obj.a = e.target.value })
源码解析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 new Vue({ data:{ a:1 }, methods:{ } }) function Vue(options) { this.data = options.data; this.methods = options.methods; var self = this; //循环data中的数据,每个key做代理 Object.keys(this.data).forEach(function(key){ self.proxyKeys(key) }) observe(this.data) } Vue.prototype = { proxyKeys:function(key){ var self = this; //注意:这里this代表vm实例,绑定data中的key直接到vm上,就实现了 vm.key = vm.data.key的效果 //所以你代码里写this.a = this.data.a Object.defineProperty(this,key,{ enumerable:false, configurable:true, get:function() { return self.data[key] }, set:function(newVal){ self[data].key = newVal; } }) } } //Observer 作用就是遍历所有的data 为其中所有的属性(可能有递归)添加观察者(getter) ,数据有变化应该通知观察者(setter) dep就是一个观察者列表,有添加(需要观察的属性),有通知功能(通知wather)调用自身的update方法 function Observe(data) { this.data = data; this.walk(data) } Observe.prototype = { walk:function(data) { var self = this; Object.keys(data).forEach(function(key) { self.defineReactive(data,key,data[key]) }) }, defineReactive:function(data,key,val){ var dep = new Dep() //如果data中的值还是对象,递归 var childObj = observe(val); Object.defineProperty(data,key,{ enumerable:true, configurable:true, get:function getter() { if(Dep.target) { //Dep.target就是watcher dep.addSub(Dep.target) } return val }, set:function setter(newVal) { val === newVal ? return : val = newVal; dep.notify() } }) } } function Dep() { this.subs = [] } Dep.prototype = { addSub:function(sub) { this.subs.push(sub) }, notify:function() { this.subs.forEach(function(sub) { sub.update(); }) } } Dep.target = null; function observe(val) { if(!val || typeof val !== Object) { return } return new Observe(value) }