vue2和vue3的響應式原理有何不同?

大家好,我是 V 哥。
Vue 2 和 Vue 3 在響應式原理上存在顯著差異,下面為你詳細介紹。

如果你是前端開發,V 哥建議抓緊入坑鴻蒙,2025年鴻蒙趨勢將引領國產化替代的新征程,大量內推崗位等你來拿。

推薦一本鴻蒙 NEXT 書《鴻蒙 HarmonyOS 開發之路》卷1,可以讓你少走彎路。

image.png

Vue 2 響應式原理

Vue 2 使用 Object.defineProperty() 方法來實現響應式系統。該方法可以直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,并返回這個對象。

實現原理

  • 核心方法Object.defineProperty() 劫持對象屬性的 gettersetter。當一個 Vue 實例創建時,Vue 會遍歷 data 選項中的所有屬性,使用 Object.defineProperty() 將這些屬性轉換為 getter/setter
  • 依賴收集:當訪問這些屬性時,觸發 getter,進行依賴收集;當屬性值發生變化時,觸發 setter,通知所有依賴更新。

示例代碼

// 模擬 Vue 2 的響應式原理
function defineReactive(obj, key, val) {
    // 存儲依賴的數組
    const dep = [];

    Object.defineProperty(obj, key, {
        get() {
            // 收集依賴
            if (Dep.target) {
                dep.push(Dep.target);
            }
            return val;
        },
        set(newVal) {
            if (newVal !== val) {
                val = newVal;
                // 通知所有依賴更新
                dep.forEach(watcher => watcher.update());
            }
        }
    });
}

// 模擬 Watcher
class Watcher {
    constructor() {
        Dep.target = this;
    }
    update() {
        console.log('數據更新,觸發視圖更新');
    }
}

// 全局變量,用于存儲當前正在收集依賴的 Watcher
Dep.target = null;

// 創建一個對象
const obj = {};
// 使對象的屬性變為響應式
defineReactive(obj, 'message', 'Hello, Vue 2!');

// 創建一個 Watcher
new Watcher();
// 訪問屬性,觸發 getter 進行依賴收集
console.log(obj.message);

// 修改屬性,觸發 setter 通知依賴更新
obj.message = 'New message';

局限性

  • 無法檢測對象屬性的添加和刪除:因為 Object.defineProperty() 是對對象已有屬性進行劫持,新增或刪除屬性時無法自動觸發響應式更新。
  • 無法檢測數組的某些變化:Vue 2 對數組的 pushpop 等方法進行了重寫,但對于通過索引直接修改數組元素或修改數組長度的操作無法檢測。

Vue 3 響應式原理

Vue 3 使用 ES6 的 Proxy 對象來實現響應式系統。Proxy 對象用于創建一個對象的代理,從而可以對該對象的基本操作進行攔截和自定義。

實現原理

  • 核心方法Proxy 可以攔截對象的各種操作,包括屬性讀取、屬性設置、屬性刪除等。Vue 3 通過創建一個 Proxy 對象來代理 data 對象,當對代理對象進行操作時,會觸發相應的攔截器。
  • 依賴收集和更新:在攔截器中進行依賴收集和更新通知,實現響應式。

示例代碼

// 模擬 Vue 3 的響應式原理
function reactive(target) {
    // 存儲依賴的 WeakMap
    const targetMap = new WeakMap();

    function track(target, key) {
        let depsMap = targetMap.get(target);
        if (!depsMap) {
            targetMap.set(target, (depsMap = new Map()));
        }
        let dep = depsMap.get(key);
        if (!dep) {
            depsMap.set(key, (dep = new Set()));
        }
        if (activeEffect) {
            dep.add(activeEffect);
        }
    }

    function trigger(target, key) {
        const depsMap = targetMap.get(target);
        if (!depsMap) return;
        const dep = depsMap.get(key);
        if (dep) {
            dep.forEach(effect => effect());
        }
    }

    return new Proxy(target, {
        get(target, key) {
            // 收集依賴
            track(target, key);
            return target[key];
        },
        set(target, key, value) {
            target[key] = value;
            // 通知依賴更新
            trigger(target, key);
            return true;
        }
    });
}

// 模擬 effect
let activeEffect;
function effect(fn) {
    activeEffect = fn;
    fn();
    activeEffect = null;
}

// 創建一個對象
const obj = { message: 'Hello, Vue 3!' };
// 使對象變為響應式
const reactiveObj = reactive(obj);

// 創建一個 effect
effect(() => {
    console.log(reactiveObj.message);
});

// 修改屬性,觸發響應式更新
reactiveObj.message = 'New message';

優勢

  • 可以檢測對象屬性的添加和刪除Proxy 可以攔截對象屬性的添加和刪除操作,從而實現響應式更新。
  • 可以檢測數組的所有變化Proxy 可以攔截數組的所有操作,包括通過索引直接修改數組元素和修改數組長度。

所以,Vue 3 的響應式原理相比 Vue 2 更加完善和強大,解決了 Vue 2 中存在的一些局限性。

Vue 2 和 Vue 3 的響應式原理對性能有什么影響?

Vue 2 和 Vue 3 的響應式原理在多個方面對性能產生不同的影響,下面從初始化性能、更新性能、內存占用等方面進行詳細分析。

初始化性能

Vue 2

  • 原理特點:Vue 2 使用 Object.defineProperty()data 選項中的每個屬性進行遞歸遍歷,并將其轉換為 getter/setter。這意味著在初始化時,需要對對象的所有屬性進行處理,對于嵌套層級較深的對象,會帶來較大的性能開銷。
  • 性能影響:當數據對象非常大且嵌套層級很深時,初始化過程會比較耗時,因為需要為每個屬性都調用 Object.defineProperty() 方法。例如,一個包含大量嵌套對象和數組的復雜數據結構,初始化時會顯著增加 CPU 的計算負擔。

Vue 3

  • 原理特點:Vue 3 使用 Proxy 對象來實現響應式。Proxy 是對整個對象進行代理,不需要對每個屬性進行遞歸處理。在初始化時,只需要創建一個 Proxy 對象,當訪問對象的屬性時才會進行依賴收集。
  • 性能影響:相比 Vue 2,Vue 3 的初始化性能有明顯提升,尤其是對于大型數據對象。因為它避免了對所有屬性的遞歸處理,減少了初始化時的計算量。

更新性能

Vue 2

  • 原理特點:當修改 Vue 2 中響應式對象的屬性時,會觸發 setter 方法,通知所有依賴更新。但由于 Object.defineProperty() 的局限性,對于對象屬性的添加和刪除以及數組的某些操作(如通過索引直接修改數組元素),無法自動檢測,需要使用特殊的方法(如 Vue.setVue.delete)來觸發更新。
  • 性能影響:在更新操作時,如果使用不當,可能會導致不必要的更新或無法及時更新。而且,由于依賴收集是基于屬性的 gettersetter,對于嵌套層級較深的對象,更新時可能需要層層觸發 setter,性能開銷較大。

Vue 3

  • 原理特點:Vue 3 的 Proxy 可以攔截對象的各種操作,包括屬性的添加、刪除和數組的所有操作。當修改響應式對象時,Proxy 會立即捕獲到變化,并通知所有依賴更新。
  • 性能影響:Vue 3 的更新性能更加穩定和高效。它能夠更準確地檢測到對象的變化,避免了 Vue 2 中因操作不當導致的更新問題。同時,由于 Proxy 的攔截機制,更新操作的響應速度更快,減少了不必要的性能損耗。

內存占用

Vue 2

  • 原理特點:由于 Vue 2 需要為每個屬性創建 getter/setter,并且需要維護一個依賴收集系統,這會增加額外的內存開銷。對于大型數據對象,每個屬性都有對應的 getter/setter 和依賴信息,會占用較多的內存空間。
  • 性能影響:在處理大量數據時,Vue 2 的內存占用可能會成為性能瓶頸,尤其是在內存有限的設備上,可能會導致頁面卡頓或崩潰。

Vue 3

  • 原理特點:Vue 3 的 Proxy 只需要為整個對象創建一個代理,不需要為每個屬性添加額外的 getter/setter,因此內存占用相對較少。同時,Vue 3 的依賴收集系統也進行了優化,減少了不必要的內存開銷。
  • 性能影響:Vue 3 在內存使用上更加高效,能夠更好地處理大型數據對象,減少了因內存占用過高導致的性能問題。

所以我們可以看到,Vue 3 的響應式原理在初始化性能、更新性能和內存占用方面都優于 Vue 2,尤其是在處理大型數據對象時,性能提升更為明顯。

最后

如果你還在老項目中使用 Vue2,V 哥強烈建議更新成 Vue3,老項目的兼容性也許會給你帶來一些麻煩,請相信,相比Vue3帶來的性能提升,會大大提高系統的用戶體驗,不防試試。關注威哥愛編程,全棧開發就你行。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容