Vue中從改變一個數據到頁面渲染改變的過程
Vue2 利用definedProperty實現數據綁定
definedProperty 基礎使用:
var ob={
a:1,
b:2
}
var _value=ob.a
Object.defineProperty(ob,'a',{
//writable:true,//可否修改
//enumerable:false,//是否可被枚舉
//configurable:false,//是否可被delete
get(){//獲取時觸發函數
console.log('取值')
return _value
},
set(a){//修改時觸發函數,參數爲修改的值
console.log('存值')
_value=a
return _value
},
})
實現Vue2 雙向數據綁定
function vue(){
this.$data={a:1};
this.el=document.getElementById('add');
this.virtualdom="";
this.observe(this.$data);
this.render;
}
vue.prototype.observe=function(obj){//數據監聽
var value;
var self=this;
for(var key in obj){
vaule=obj[key];
if(typeof vaue=='object'){
this.observe(value)
}else{
Object.defineProperty(obj,key,{
get(){//依賴收集
return value
},
set(newValue){//觸發更新
value=newValue
self.render()
},
})
}
}
}
vue.prototype.render=function(){//數據渲染
this.virtualdom="I am "+this.$data.a
this.el.innerHTML=this.virtualdom
}
//數組監聽~思想(未具體實現)
var arrPro=Array.prototype;
var arrayob=Object.create(arrayPro)
var arr=['push','pop','shift'];
arr.forEach((method,index)=>{
arrayob[methods]=function(){
var ret=arrayPro[methods].apply(this,arguments);
dep.notify();//vue源碼中體現
return ret;
}
})
let num=0
let vm=new vue()
setInterval(()=>{
console.log('修改')
vm.$data.a=num++
},2000)
Vue3 利用proxy實現數據綁定
和defineProperty類似,功能幾乎一樣,用法不同
- defineProperty是改變原有對象
- proxy是新建一個代理對象
- defineProperty只能監聽某一屬性不能設置去全對象監聽;如果需要全對象監聽則需要遞歸修改原對象相關屬性,且defineProperty是對象的方法 數組無法監聽;proxy可以對數組進行監聽
Proxy用於修改某些操作的默認行爲,也可以理解爲在目標對象之前架設一層攔截,外部所有的訪問都必須先通過這層攔截,因此提供了一種機制,可以對外部的訪問進行過濾和修改。這個詞的原理爲代理,在這裏可以表示由它來“代理”某些操作,譯爲“代理器”。
實現Vue3雙向數據綁定
function vue(){
this.$data={a:1};
this.el=document.getElementById('add');
this.virtualdom="";
this.observe(this.$data);
this.render;
}
vue.prototype.observe=function(obj){//數據監聽
var self=this;
this.$data=new Proxy(this.$data,{
get(target,key){
return target[key]
},
set(target,key,newValue){//觸發更新
target[key]=newValue
self.render()
},
})
}
vue.prototype.render=function(){//數據渲染
this.virtualdom="I am "+this.$data.a
this.el.innerHTML=this.virtualdom
}
let num=0
let vm=new vue()
setInterval(()=>{
console.log('修改')
vm.$data.a=num++
},2000)