Vue2和Vue3的雙向數(shù)據(jù)綁定原理分析
vue2.x 是如何實(shí)現(xiàn)響應(yīng)式系統(tǒng)的
當(dāng)你把一個(gè)普通的 js 對象傳入 vue 實(shí)例作為 data 選項(xiàng),vue 將遍歷此對象的所有prototype(屬性),并使用 object.defineProperty(),將這些 prototype(屬性),全部轉(zhuǎn)換為 getter / setter,在 getter 中收集數(shù)據(jù)依賴,在 setter 中監(jiān)聽數(shù)據(jù)變化,一旦數(shù)據(jù)發(fā)生改變,在通知訂閱者。
每個(gè)組件實(shí)例,都對應(yīng)一個(gè) watcher 實(shí)例,它會(huì)在組件渲染的過程把 “接觸” 過的數(shù)據(jù) prototype(屬性)記錄為依賴,之后當(dāng)依賴項(xiàng)的 setter 觸發(fā)時(shí),會(huì)通知 watcher,從而使它關(guān)聯(lián)的組件重新渲染;
defineProperty 的痛點(diǎn)
- 它無法發(fā)現(xiàn)對象新增和被刪除的屬性,當(dāng)你給一個(gè)對象添加一個(gè)新的屬性,這個(gè)新增的屬性沒有添加到 vue 的數(shù)據(jù)更新偵查機(jī)制里;
Vue.set() 可以讓 vue 知道你新增了一個(gè)屬性,其實(shí) Vue.set 可以讓 Vue 知道新增了一個(gè)屬性。其實(shí) set() 內(nèi)部也是通過調(diào)用 defineProperty() 來實(shí)現(xiàn);
- 當(dāng)你利用索引直接設(shè)置一個(gè)數(shù)組(new Array(4))或者修改數(shù)組的長度時(shí),Vue 不能檢測到數(shù)組的變動(dòng);
- 當(dāng)對象嵌套的層數(shù)特別深(多層嵌套)的時(shí)候,遞歸遍歷帶來的性能開銷就會(huì)比較大;
Object.defineProperty 代碼的使用
mounted() {
// 先定義好一套規(guī)則
class Observer {
constructor(data) {
for (let key of Object.keys(data)) {
if (typeof data[key] === "object") {
data[key] = new Observer(data[key]);
}
Object.defineProperty(this, key, {
enumerable: true,
configurable: true,
get() {
console.log("You visited" + key);
return data[key];
},
set(NewValue) {
console.log("You set" + key);
console.log("New Value" + NewValue);
if (NewValue === data[key]) {
return;
}
data[key] = NewValue;
},
});
}
}
}
let obj = {
name: "app",
age: 18,
a: {
b: 1,
c: {
d: 1,
},
},
};
let app = new Observer(obj);
console.log(app);
app.age = 20;
app.newProperty = "new attrs";
console.log(app);
},結(jié)果:

Proxy 方法的理解
Proxy 在 vue3.0 中上位
可以解決 defineProperty 的痛點(diǎn),因?yàn)楸举|(zhì)的原因在于 Proxy 是內(nèi)置了攔截器對象。所有的外部訪問都得先經(jīng)過這一層攔截,不管是先前定義好的,還是新增的屬性,又或者是深層的嵌套屬性,訪問時(shí)都會(huì)被攔截;
Reflect.set()方法用于設(shè)置對象屬性的值,1:目標(biāo)對象:2:改變參數(shù)的名稱:3:改變參數(shù)的值:4:值是this如果遇到設(shè)置器,將提供給目標(biāo)調(diào)用。
此方法返回一個(gè)布爾值,該值指示該屬性是否已成功設(shè)置。
Proxy 代碼的使用
mounted() {
const obj = {
name: "app",
age: 19,
a: {
b: 1,
c: 2,
},
};
const p = new Proxy(obj, {
get(target, propKey, receiver) {
console.log("Your visited:" + propKey);
// Reflect.set()方法用于設(shè)置對象屬性的值:1:目標(biāo)對象:2:改變參數(shù)的名稱:3:改變參數(shù)的值
// 此方法返回一個(gè)布爾值,該值指示該屬性是否已成功設(shè)置。
return Reflect.set(target, propKey, receiver);
},
set(target, propKey, value, receiver) {
console.log("You set:" + propKey);
console.log("New value:" + value);
// Reflect.set()方法用于設(shè)置對象屬性的值,1:目標(biāo)對象:2:改變參數(shù)的名稱:3:改變參數(shù)的值:4:值是this如果遇到設(shè)置器,將提供給目標(biāo)調(diào)用。
// 此方法返回一個(gè)布爾值,該值指示該屬性是否已成功設(shè)置。
return Reflect.set(target, propKey, value, receiver);
},
});
p.age = "20";
console.log(p);
p.newProperty = "New attribute";
console.log(p);
},結(jié)果:

總結(jié)
- proxy 是用來操作對象并且擴(kuò)展對象能到,而 Object.defineProperty() 只是單純的操作對象的屬性;
- Vue2.X 是用 Object.defineProperty() 實(shí)現(xiàn)數(shù)據(jù)響應(yīng)的,但是受限于 defineProperty() 的實(shí)現(xiàn),必須遞歸遍歷至對象的最底層;
- vue3.0 用 Proxy 來攔截對象,不管對目標(biāo)執(zhí)行任何操作,都會(huì)先通過 Proxy 的處理邏輯;
- 除了 Vue3.0,還有其他的庫也在使用 Proxy。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue 對axios get pust put delete封裝的實(shí)例代碼
在本篇文章里我們給各位整理的是一篇關(guān)于vue 對axios get pust put delete封裝的實(shí)例代碼內(nèi)容,有需要的朋友們可以參考下。2020-01-01
解決vuejs 使用value in list 循環(huán)遍歷數(shù)組出現(xiàn)警告的問題
今天小編就為大家分享一篇解決vuejs 使用value in list 循環(huán)遍歷數(shù)組出現(xiàn)警告的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
vue項(xiàng)目多租戶環(huán)境變量的設(shè)置
本文主要介紹了vue項(xiàng)目多租戶環(huán)境變量的設(shè)置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
vue+vant實(shí)現(xiàn)商品列表批量倒計(jì)時(shí)功能
這篇文章主要介紹了vue+vant實(shí)現(xiàn)商品列表批量倒計(jì)時(shí)功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
vue 界面刷新數(shù)據(jù)被清除 localStorage的使用詳解
今天小編就為大家分享一篇vue 界面刷新數(shù)據(jù)被清除 localStorage的使用詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
select的change方法傳遞多個(gè)參數(shù)的方法詳解
element-ui中的select,checkbox等組件的change方法的回調(diào)函數(shù)只有當(dāng)前選擇的val,如果想再傳入自定義參數(shù)怎么辦,本文給大家分享select的change方法如何傳遞多個(gè)參數(shù),感興趣的朋友一起看看吧2024-02-02
Vue 框架之動(dòng)態(tài)綁定 css 樣式實(shí)例分析
這篇文章主要介紹了Vue 框架之動(dòng)態(tài)綁定 css 樣式的方法,本文通過分享小實(shí)例給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11

