Vue3和Vue2響應(yīng)式的區(qū)別

1.拉開(kāi)序幕的setup

理解:Vue3.0中一個(gè)新的配置項(xiàng),值為一個(gè)函數(shù)。

setup是所有Composition API(組合API)“ 表演的舞臺(tái) ”。

組件中所用到的:數(shù)據(jù)、方法等等,均要配置在setup中。

setup函數(shù)的兩種返回值:

若返回一個(gè)對(duì)象,則對(duì)象中的屬性、方法, 在模板中均可以直接使用。(重點(diǎn)關(guān)注!)

若返回一個(gè)渲染函數(shù):則可以自定義渲染內(nèi)容。(了解)

注意點(diǎn):

盡量不要與Vue2.x配置混用

Vue2.x配置(data、methos、computed...)中可以訪(fǎng)問(wèn)到setup中的屬性、方法。

但在setup中不能訪(fǎng)問(wèn)到Vue2.x配置(data、methos、computed...)。

如果有重名, setup優(yōu)先。

setup不能是一個(gè)async函數(shù),因?yàn)榉祷刂挡辉偈莚eturn的對(duì)象, 而是promise, 模板看不到return對(duì)象中的屬性。(后期也可以返回一個(gè)Promise實(shí)例,但需要Suspense和異步組件的配合)

2.ref函數(shù)

作用: 定義一個(gè)響應(yīng)式的數(shù)據(jù)

語(yǔ)法: const xxx = ref(initValue)

創(chuàng)建一個(gè)包含響應(yīng)式數(shù)據(jù)的引用對(duì)象(reference對(duì)象,簡(jiǎn)稱(chēng)ref對(duì)象)。

JS中操作數(shù)據(jù): xxx.value

模板中讀取數(shù)據(jù): 不需要.value,直接:<div>{{xxx}}</div>

備注:

接收的數(shù)據(jù)可以是:基本類(lèi)型、也可以是對(duì)象類(lèi)型。

基本類(lèi)型的數(shù)據(jù):響應(yīng)式依然是靠Object.defineProperty()的get與set完成的。

對(duì)象類(lèi)型的數(shù)據(jù):內(nèi)部 “ 求助 ” 了Vue3.0中的一個(gè)新函數(shù)—— reactive函數(shù)。

3.reactive函數(shù)

作用: 定義一個(gè)對(duì)象類(lèi)型的響應(yīng)式數(shù)據(jù)(基本類(lèi)型不要用它,要用ref函數(shù))

語(yǔ)法:const 代理對(duì)象= reactive(源對(duì)象)接收一個(gè)對(duì)象(或數(shù)組),返回一個(gè)代理對(duì)象(Proxy的實(shí)例對(duì)象,簡(jiǎn)稱(chēng)proxy對(duì)象)

reactive定義的響應(yīng)式數(shù)據(jù)是“深層次的”。

內(nèi)部基于 ES6 的 Proxy 實(shí)現(xiàn),通過(guò)代理對(duì)象操作源對(duì)象內(nèi)部數(shù)據(jù)進(jìn)行操作。

4.Vue3.0中的響應(yīng)式原理

vue2.x的響應(yīng)式

實(shí)現(xiàn)原理:

對(duì)象類(lèi)型:通過(guò)Object.defineProperty()對(duì)屬性的讀取、修改進(jìn)行攔截(數(shù)據(jù)劫持)。

數(shù)組類(lèi)型:通過(guò)重寫(xiě)更新數(shù)組的一系列方法來(lái)實(shí)現(xiàn)攔截。(對(duì)數(shù)組的變更方法進(jìn)行了包裹)。

Object.defineProperty(data,'count', {

get() {},

set() {}

})

存在問(wèn)題:

新增屬性、刪除屬性, 界面不會(huì)更新。

直接通過(guò)下標(biāo)修改數(shù)組, 界面不會(huì)自動(dòng)更新。

Vue3.0的響應(yīng)式

實(shí)現(xiàn)原理:

通過(guò)Proxy(代理):? 攔截對(duì)象中任意屬性的變化, 包括:屬性值的讀寫(xiě)、屬性的添加、屬性的刪除等。

通過(guò)Reflect(反射):? 對(duì)源對(duì)象的屬性進(jìn)行操作。

MDN文檔中描述的Proxy與Reflect:

Proxy:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Reflect:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

newProxy(data, {

? ? // 攔截讀取屬性值

get(target,prop) {

? ? returnReflect.get(target,prop)

?? },

// 攔截設(shè)置屬性值或添加新屬性

set(target,prop,value) {

? ? returnReflect.set(target,prop,value)

?? },

// 攔截刪除屬性

deleteProperty(target,prop) {

? ? returnReflect.deleteProperty(target,prop)

?? }

})

proxy.name='tom'

5.reactive對(duì)比ref

從定義數(shù)據(jù)角度對(duì)比:

ref用來(lái)定義:基本類(lèi)型數(shù)據(jù)。

reactive用來(lái)定義:對(duì)象(或數(shù)組)類(lèi)型數(shù)據(jù)。

備注:ref也可以用來(lái)定義對(duì)象(或數(shù)組)類(lèi)型數(shù)據(jù), 它內(nèi)部會(huì)自動(dòng)通過(guò)reactive轉(zhuǎn)為代理對(duì)象

從原理角度對(duì)比:

ref通過(guò)Object.defineProperty()的get與set來(lái)實(shí)現(xiàn)響應(yīng)式(數(shù)據(jù)劫持)。

reactive通過(guò)使用Proxy來(lái)實(shí)現(xiàn)響應(yīng)式(數(shù)據(jù)劫持), 并通過(guò)Reflect操作源對(duì)象內(nèi)部的數(shù)據(jù)。

從使用角度對(duì)比:

ref定義的數(shù)據(jù):操作數(shù)據(jù)需要.value,讀取數(shù)據(jù)時(shí)模板中直接讀取不需要.value。

reactive定義的數(shù)據(jù):操作數(shù)據(jù)與讀取數(shù)據(jù):均不需要.value。

6.setup的兩個(gè)注意點(diǎn)

setup執(zhí)行的時(shí)機(jī)

在beforeCreate之前執(zhí)行一次,this是undefined。

setup的參數(shù)

props:值為對(duì)象,包含:組件外部傳遞過(guò)來(lái),且組件內(nèi)部聲明接收了的屬性。

context:上下文對(duì)象

attrs: 值為對(duì)象,包含:組件外部傳遞過(guò)來(lái),但沒(méi)有在props配置中聲明的屬性, 相當(dāng)于 this.$attrs。

slots: 收到的插槽內(nèi)容, 相當(dāng)于 this.$slots。

emit: 分發(fā)自定義事件的函數(shù), 相當(dāng)于 this.$emit。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容