淺析Vue為什么需要同時使用Ref和Reactive
在使用 Options API 工作時聲明響應(yīng)性數(shù)據(jù)是直截了當?shù)摹?code>data 選項內(nèi)的所有內(nèi)容都會自動變?yōu)轫憫?yīng)性,并在模板中可用。唯一需要注意的是,要將data
設(shè)為一個函數(shù),以防止在所有組件實例之間共享狀態(tài)。
讓我們討論一下Vue 3中發(fā)生了什么變化,以及為什么我們需要兩個不同的助手。
Vue 2中的響應(yīng)性
data
組件選項內(nèi)的每個屬性都將通過 Object.defineProperty
轉(zhuǎn)換為getter/setter
。這些getter/setter
對我們來說是看不見的,但在底層,它們使Vue在訪問或修改屬性時能夠執(zhí)行依賴跟蹤。
每個組件都有一個關(guān)聯(lián)的觀察者,用于跟蹤在組件的渲染周期中使用的屬性。如果依賴項更新,觀察者會通知組件,然后觸發(fā)重新渲染。
Vue 3中的響應(yīng)性
在 Vue 3 中,一切都發(fā)生了變化。核心部分從零開始重寫,現(xiàn)在由Javascript Proxies
提供響應(yīng)性。Proxies是一種現(xiàn)代且優(yōu)雅的方式來觀察一個對象并在其屬性被訪問或更新時得到通知。
可以通過以下簡單的例子來理解代理是如何工作的:
const userInfo = { firstName: "fotis", age: 35, }; const handler = { get(target, property) { if (property === "firstName") { const name = target[property] return name.charAt(0).toUpperCase() + name.slice(1); } if (property === "age") { return '--' } return target[property] }, }; const proxy = new Proxy(userInfo, handler); console.log(proxy.firstName) // "Fotis" console.log(proxy.age) // "--"
處理器內(nèi)部的get
方法被稱為陷阱,每次訪問對象的屬性時都會被調(diào)用。以類似的方式,可以定義一個設(shè)定的陷阱:
const userInfo = { firstName: "Fotis", age: 35, }; const handler = { set(target, prop, value) { if (prop === "age") { if (!Number.isInteger(value)) { throw new TypeError("The age is not an integer"); } if (value > 200) { throw new RangeError("The age seems invalid"); } } target[prop] = value; return true; }, }; const proxy = new Proxy(userInfo, handler); proxy.age = 12 // OK proxy.age = 300 // Error: The age seems invalid
這正是 Vue 3 響應(yīng)性背后的理念。當使用 reactive
助手聲明一個變量時,會使用一個 proxy. 來跟蹤任何變化。
function reactive(obj) { return new Proxy(obj, { get(target, key) { track(target, key) return target[key] }, set(target, key, value) { target[key] = value trigger(target, key) } }) }
當然,響應(yīng)式助手的實際實現(xiàn)更為復(fù)雜,能處理邊緣情況,但其核心仍然使用proxy。
以上的片段解釋了為什么將響應(yīng)性變量解構(gòu)或重新分配給本地變量后,它就不再具有反應(yīng)性,因為它不再觸發(fā)源對象上的 get/set
proxy 陷阱。
這看起來像是一個完美的解決方案,可以使所有事物都變成響應(yīng)式。但是有個問題!根據(jù)定義,proxy只適用于復(fù)雜類型。這些包括對象、數(shù)組、映射和集合。要使一個原始類型變得反應(yīng)靈敏,我們?nèi)匀恍枰褂么?,但首先我們必須將其包裝在一個對象中。
function ref(value) { const refObject = { get value() { track(refObject, 'value') return value }, set value(newValue) { value = newValue trigger(refObject, 'value') } } return refObject }
這解釋了為什么必須在 script setup
中使用煩人的 .value
。而且,再次重構(gòu)或重新分配給本地變量也是行不通的。
總結(jié)
那么,為什么需要 Ref 和 Reactive的答案是:Proxy。對于復(fù)雜類型,它們可以直接使用,但對于原始類型,需要創(chuàng)建一個代理對象。
希望,理解Vue的內(nèi)部工作原理可以使你更有效,并且可以消除 ref
和 reactive
之間的任何混淆。
以上就是淺析Vue為什么需要同時使用Ref和Reactive的詳細內(nèi)容,更多關(guān)于Vue Ref Reactive的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何解決this.$refs.form.validate()不執(zhí)行的問題
這篇文章主要介紹了如何解決this.$refs.form.validate()不執(zhí)行的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09Element的el-tree控件后臺數(shù)據(jù)結(jié)構(gòu)的生成以及方法的抽取
這篇文章主要介紹了Element的el-tree控件后臺數(shù)據(jù)結(jié)構(gòu)的生成以及方法的抽取,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Vue項目之ES6裝飾器在項目實戰(zhàn)中的應(yīng)用
作為一個曾經(jīng)的Java?coder,當?shù)谝淮慰吹絡(luò)s里面的裝飾器Decorator,就馬上想到了Java中的注解,當然在實際原理和功能上面,Java的注解和js的裝飾器還是有很大差別的,這篇文章主要給大家介紹了關(guān)于Vue項目之ES6裝飾器在項目實戰(zhàn)中應(yīng)用的相關(guān)資料,需要的朋友可以參考下2022-06-06vue-admin-template模板添加tagsview的實現(xiàn)
本文主要介紹了vue-admin-template模板添加tagsview的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04解決vue-element-admin中配置跨域出現(xiàn)的問題
這篇文章主要介紹了解決vue-element-admin中配置跨域出現(xiàn)的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07