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;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。