vue实现动态数据绑定
实现的步骤:
1.监听对象属性的读取与变化
Object.defineProperty()方法会直接在对象上定义一个新的的属性,或者已经存在的属性并且返回这个属性
语法是Object.defineProperty(obj,prop,descript)
obj:目标对象
prop:需要定义或修改的属性的名字
descript:将被定义或修改的属性的描述符
描述:
这个方法精确添加或修改对象的属性,我们添加的属性是可以枚举的属性(Object.keys()/for...in)
对象里面存在是属性描述存在的形式是:
数据描述符:拥有可写入或不可以写入的属性(相当于口令密码)
存取描述符:由一对getter-setter函数功能来描述的属性(方法)
注意:**描述符**必须是两种形式之一,不能同时是两者。
数据描述符和存取描述符均具有以下可选键值:
1.configurable:当且仅当该属性的configurable为true时,该属性描述符才能够被改变,也能够被删除。默认为false
2.enumerable:当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为false
数据描述符:
1.value:该属性对应的值。可以是任何有效的JavaScript值(数值,对象,函数等)。默认为undefined。
2.writable:当且仅当该属性的writable为true时,该属性才能被赋值运算符改变。默认为false。
存取描述符同时具有以下可选键值:
1.get:一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined。
2.set:一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为undefined。
示例:
创建属性
varo={}; Object.defineProperty(o,"a",{value:37, writable:true, enumerable:true, configurable:true}); console.log(o.a); Object.defineProperty(o,"b",{get:function(){/*console.log(bValue)*/returnvalue}, set:function(newValue){bValue=newValue;}, enumerable:true, configurable:true}); o.b=38;
修改属性
当属性特性(propertyattribute)writable设置为false时,表示non-writable,属性不能被修改。
varo={};//创建一个新对象 Object.defineProperty(o,"a",{value:37, writable:false}); console.log(o.a);//打印37 o.a=25;//没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值) console.log(o.a);//打印37,赋值不起作用。
一般的setter和getters
varpattern={ get:function(){ return'Ialwayreturnthisstring,whateveryouhaveassigned'; }, set:function(){ this.myname='thisismynamestring'; } }; functionTestDefineSetAndGet(){ Object.defineProperty(this,'myproperty',pattern); } varinstance=newTestDefineSetAndGet(); instance.myproperty='test'; //'Ialwayreturnthisstring,whateveryouhaveassigned' console.log(instance.myproperty); //'thisismynamestring' console.log(instance.myname);
解题
functionObserver(property){ this.data={}; this.recursion(data); } Observer.prototype.recursion=function(obj){ varval=null; for(keyinobj){ if(obj.hasOwnProperty(key)){ val=obj[val]; if(typeofval==='object'&&!!val){ newObserver(val); } this.access(key,val); } } } Observer.prototype.access=function(key,val){ Object.defineProperty(this.data,key,{ enumerable:true, configurable:true, get:function(){ console.log('你访问了'+key); returnval }, set:function(newVal){ console.log('你设置了'+key); console.log('新的'+key+'='+newVal) if(newVal===val)return; val=newVal } }) } letapp1=newObserver({ name:'youngwind', age:25 }); letapp2=newObserver({ university:'bupt', major:'computer' }); //要实现的结果如下: app1.data.name//你访问了name app1.data.age=100;//你设置了age,新的值为100 app2.data.university//你访问了university app2.data.major='science'//你设置了major,新的值为science
多层级对象
当传入的对象是
letapp1=newObserver({ user:{ name:"liangshaofeng", age:"24" }, address:{ city:"beijing" } });
递归解决问题!!
functionObserver(data){ this.data=data; this.recursion(this.data); } Observer.prototype.recursion=function(obj){ varval=null; for(keyinobj){ if(obj.hasOwnProperty(key)){ val=obj[key]; if(typeofval==='object'&&!!val){ newObserver(val); } this.access(key,val); } } } Observer.prototype.access=function(key,val){ Object.defineProperty(this.data,key,{ enumerable:true, configurable:true, get:function(){ console.log('你访问了'+key); returnval }, set:function(newVal){ console.log('你设置了'+key); console.log('新的'+key+'='+newVal) if(newVal===val)return; val=newVal } }) } letapp1=newObserver({ user:{ name:"liangshaofeng", age:"24" }, address:{ city:"beijing" } }); app1.data.user.name//你访问了name app1.data.user.age=100;//你设置了age,新的值为100
增加事件系统
//事件系统 functionEvent(){ this.events={}; } Event.prototype.emit=function(attr,val,newVal){ this.events[attr]&&this.events[attr].forEach(function(item){ item(val,newVal) }) } Event.prototype.on=function(attr,callback){ if(this.events[attr]){ this.events[attr].push(callback); }else{ this.events[attr]=[callback]; } } functionObserver(data){ this.data=data; this.recursion(this.data); this.eventsBus=newEvent(); } Observer.prototype.recursion=function(obj){ varval=null; for(keyinobj){ if(obj.hasOwnProperty(key)){ val=obj[key]; if(typeofval==='object'&&!!val){ newObserver(val); } this.access(key,val); } } } Observer.prototype.access=function(key,val){ varself=this; Object.defineProperty(this.data,key,{ enumerable:true, configurable:true, get:function(){ console.log('你访问了'+key); returnval }, set:function(newVal){ if(typeofnewVal==='object'&&!!newVal){ newObserver(newVal); } console.log('你设置了'+key); console.log('新的'+key+'='+newVal) self.eventsBus.emit(key,val,newVal); if(newVal===val)return; val=newVal } }) } Observer.prototype.$watch=function(attr,callback){ this.eventsBus.on(attr,callback); } letapp1=newObserver({ user:{ name:"liangshaofeng", age:"24" }, address:{ city:"beijing" } }); app1.data.user.name//你访问了name app1.data.user.age=100;//你设置了age,新的值为100 app1.data.user.name={ lastName:'liang', firstName:'shaofeng' }; app1.data.user.name.lastName; //这里还需要输出'你访问了lastName' app1.data.user.name.firstName='lalala'; //这里还需要输出'你设置了firstName,新的值为lalala' varapp1=newObserver({ name:'liujianhuan', age:25, company:'Qihoo360', address:'Chaoyang,Beijing' }) app1.$watch('age',function(oldVal,newVal){ console.log(`我的年龄变了,原来是:${oldVal}岁,现在是:${newVal}岁了`) }) app1.$watch('age',function(oldVal,newVal){ console.log(`我的年龄真的变了诶,竟然年轻了${oldVal-newVal}岁`) }) app1.data.age=20;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。