vue的雙向數(shù)據(jù)綁定,眾所周知是基于Object.defineProperty這個(gè)在瀏覽器的特性api來(lái)實(shí)現(xiàn)的。但是怎么從視圖到數(shù)據(jù),數(shù)據(jù)到視圖,這個(gè)整個(gè)大過(guò)程,對(duì)于很多盆友來(lái)說(shuō),還有點(diǎn)不是很清楚。
<div id='app'>
<div>價(jià)格:¥{{price}}</div>
<div>總價(jià):¥{{price*quantity}}</div>
<div>折扣后:¥{{totlePriceWithTax}}</div>
</div>
<script>
var vm=new Vue({
el:'#app',
data:(){
price:5.00,//單價(jià)
quantity:2//數(shù)量
},
computed:{
totlePriceWithTax(){
return this.price*this.quantity*1.03
}
}
})
</script>
更新頁(yè)面顯示的price的值
重新計(jì)算總價(jià)的乘法表達(dá)式并且更新顯示結(jié)果
重新調(diào)用totlePriceWithTax函數(shù),并且更新顯示
let price=5;
let quantity=2;
let total=price*quantity;//計(jì)算總價(jià)
pice=20;//price字段發(fā)生變更之后
console.log(`變化之后的總價(jià):${total}`);
>> 變化之后的總價(jià):10
>> 變化之后的總價(jià):40
let total=price*quantity;
let price=5;
let quantity=2;
let total=0;
let target=null;
//記錄函數(shù)
target=()=>{
total=price*quantity;
}
record();//后面講解,記住這個(gè)我們后面想要運(yùn)行的函數(shù)
target();//同時(shí),我們執(zhí)行一遍這個(gè)方法
let storage=[];//這是要記錄函數(shù)的地方,就是上面圖中橢圓的那個(gè)東西
//記錄方法的實(shí)現(xiàn),這個(gè)時(shí)候的target就是我們要記錄的方法
function record(){
storage.push(target)
}
function replay(){
storage.forEach((run)=>{
run();
})
}
let price=5;
let quantity=2;
let total=0;
let target=null;
function record(){
storage.push(target)
}
function replay(){
storage.forEach((run)=>{
run();
})
}
target=()=>{
total=price*quantity;
}
record();
target();
console.log(total)// 10
price=20;
replay();
console.log(total)//40
class Dep{
constructor(){
this.subscribers=[];//維護(hù)所有target的列表,在得到通知的時(shí)候,全部都會(huì)運(yùn)行
}
depend(){
if(target&&!this.subscribers.includes(target)){
//只有target有方法,并且沒(méi)有被記錄過(guò)
this.subscribers.push(target);
}
}
notify(){
this.subscribers.forEach((sub)=>{
sub();
})
}
}
const dep=new Dep();
let price=5;
let quantity=2;
let total=0;
let target=null;
target=()=>{
total=price*quantity;
}
dep.depend();//記錄到subscribers中
target();
console.log(total)// 10
price=20;
dep.notify();//遍歷執(zhí)行所有target,分發(fā)內(nèi)容
console.log(total)//40
target=()=>{
total=price*quantity;
}
dep.depend();//記錄到subscribers中
target();
watcher(()=>{
total=price*quantity
})
function watcher(myFunc){
target=myFunc;//傳入的函數(shù)賦值
dep.depend();//收集
target();//執(zhí)行一下
target=null;//重置
}
price=20;
console.log(total);
dep.notify();
console.log(total);
let data={
price:5,
quantity:2
}
wacther(()=>{
total=data.price*data.quantity
})
>> total
10
>> price=20
>> total
40
let data={price:5,quantity:2};
Object.defineProperty(data,'price',{
get(){
console.log('被訪問(wèn)')
},
set(newVal){
console.log('被修改')
}
});
data.price;//輸出:被訪問(wèn)
data.price=20;//輸出:被修改
let data={price:5,quantity:2};
let internalValue=data.price;//初始值
Object.defineProperty(data,'price',{
get(){
console.log('被訪問(wèn)');
return internalValue
},
set(newVal){
console.log('被修改');
internalValue=newVal
}
});
total=data.price*data.quantity;//調(diào)用get
data.price=20;//調(diào)用set
let data={price:5,quantity:2};
Object.keys(data).forEach((key)=>{
let internalValue=data[key];//初始值
Object.defineProperty(data,key,{
get(){
console.log('被訪問(wèn)');
return internalValue
},
set(newVal){
console.log('被修改');
internalValue=newVal
}
});
})
total=data.price*data.quantity;//調(diào)用get
data.price=20;//調(diào)用set
total=data.price*data.quantity
Get—記住匿名函數(shù),當(dāng)值發(fā)生變化的時(shí)候重新運(yùn)行。
Set—運(yùn)行保存的匿名函數(shù),對(duì)應(yīng)匿名函數(shù)綁定的值就會(huì)發(fā)生變化
price被訪問(wèn)時(shí)—調(diào)用dep.depend保存當(dāng)前target
price被改變時(shí)—調(diào)用price的dep.notify,重新運(yùn)行所有的target
let data={price:5,quantity:2};
let target=null;
class Dep{
constructor(){
this.subscribers=[];//維護(hù)所有target的列表,在得到通知的時(shí)候,全部都會(huì)運(yùn)行
}
depend(){
if(target&&!this.subscribers.includes(target)){
//只有target有方法,并且沒(méi)有被記錄過(guò)
this.subscribers.push(target);
}
}
notify(){
this.subscribers.forEach((sub)=>{
sub();
})
}
}
Object.keys(data).forEach((key)=>{
let internalValue=data[key];//初始值
Object.defineProperty(data,key,{
get(){
console.log('被訪問(wèn)');
dep.depend();//添加對(duì)應(yīng)的匿名函數(shù)target
return internalValue
},
set(newVal){
console.log('被修改');
internalValue=newVal;
dep.notify();//觸發(fā)對(duì)應(yīng)的儲(chǔ)存的函數(shù)
}
});
})
function watcher(myFunc){
target=myFunc;//傳入的函數(shù)賦值
target();//執(zhí)行一下
target=null;//重置
}
watcher(()=>{
data.total=data.price*data.quantity;
})
本次專題課深度講解 Vue.js 性能優(yōu)化,以及 Vue3.0 那些值得關(guān)注的新特性。在高級(jí)前端崗位面試中,性能優(yōu)化是一個(gè)必問(wèn)的知識(shí)點(diǎn),本課程通過(guò)對(duì) Vue 面試核心知識(shí)點(diǎn)的拆解,帶你解鎖你可能不知道的 Vue.js 性能優(yōu)化,直達(dá)大廠offer!
大廠面試問(wèn)Vue項(xiàng)目?jī)?yōu)化時(shí)的各種講解
核心工程化知識(shí)點(diǎn)講解
不同的核心優(yōu)化方案剖析
??糣ue知識(shí)點(diǎn)串講
修正對(duì)于Object.defineProperty的錯(cuò)誤理解
Vue2中雙向數(shù)據(jù)綁定為什么性能不好?
數(shù)組的雙向數(shù)據(jù)綁定怎么處理的
淺嘗Vue3的使用
Vue3的新特性解析
Vue3核心雙向數(shù)據(jù)綁定的實(shí)現(xiàn)解析
深度對(duì)比Vue2,助你直達(dá)offer
聯(lián)系客服