我们在使用vue开发时,一般都是通过以下代码来创建Vue实例的
1 let vm = new Vue({ 2 el:"#app", 3 data:{ 4 a:1, 5 b:1 6 } 7 });
1 此次我们通过自己写一个方法类,来简单模拟Vue实现MVVM数据双向绑定 2 创建index.html测试代码 3 <div id="app"> 4 <p>{{a}}</p> 5 <p>{{b}}</p> 6 </div> 7 <script src="mvvm.js"></script> 8 <script> 9 let demo = new Demo({ 10 el:"#app", 11 data:{ 12 a:1, 13 b:1 14 } 15 }) 16 </script>
接下来是js逻辑的实现部分:
1,通过Object.defineProperty对data上的属性实现深度数据劫持
3 4 function Demo (options){ 5 //首先将options,和data绑定到实例上 6 this.$options = options; 7 let data = this._data = options.data; 8 //对data进行数据劫持处理 9 observe(this._data); 10 11 //将data数据里的属性挂载到this实例上 12 for (let key in data) { 13 Object.defineProperty(this,key,{ 14 enumerable:true, 15 get(){ 16 return this._data[key]; 17 }, 18 set(newVal){ 19 this._data[key]=newVal; 20 } 21 }) 22 } 23 } 24 25 function Observe(data){ 26 //遍历data,对每一个属性进行劫持 27 for (let key in data) { 28 let value = data[key]; 29 console.log(value); 30 Object.defineProperty(data,key,{ 31 enumerable:true, 32 get(){ 33 return value; 34 }, 35 set(newVal){ 36 value=newVal; 37 observe(value);//=>如果修改的值是一个对象,对其进行深度劫持 38 } 39 }); 40 observe(value);//=>深度劫持,如果valu是对象,继续进行劫持处理 41 } 42 } 43 function observe(data){ 44 if(typeof data !== "object") return; 45 new Observe(data); 46 }
测试结果:
输出demo,可以看见,所有data属性都具有了getter和setter属性

另外重新赋值,也会持续进行数据劫持

