系列文章目錄
內(nèi)容 | 鏈接 |
---|---|
從Vue2到Vue3【零】 | Vue3簡(jiǎn)介 |
從Vue2到Vue3【一】 | Composition API(第一章) |
從Vue2到Vue3【二】 | Composition API(第二章) |
從Vue2到Vue3【三】 | Composition API(第三章) |
從Vue2到Vue3【四】 | Composition API(第四章) |
前言
隨著Vue 3的發(fā)布,我們迎來(lái)了一套強(qiáng)大且令人興奮的組合式API,這為開(kāi)發(fā)者帶來(lái)了更多靈活性和可維護(hù)性。Vue 3的組合式API不僅改變了我們編寫(xiě)Vue組件的方式,還引入了一些新的組件和一些小的但實(shí)用的改變。在這篇文章中,我們將深入探討Vue 3的組合式API,并介紹一些引人注目的新組件和改變,讓我們一起開(kāi)始這個(gè)令人興奮的學(xué)習(xí)之旅吧!
一、shallowReactive 與 shallowRef
-
shallowReactive:
- shallowReactive函數(shù)用于創(chuàng)建一個(gè)淺響應(yīng)式對(duì)象,它只會(huì)對(duì)對(duì)象的第一層屬性進(jìn)行響應(yīng)式處理,而不會(huì)遞歸地對(duì)嵌套的屬性進(jìn)行深層次響應(yīng)式處理。
- 這在某些情況下可以提高性能和減少內(nèi)存消耗,特別是當(dāng)對(duì)象的嵌套層次很深或者對(duì)象非常大時(shí)。
- 適用場(chǎng)景:當(dāng)需要對(duì)一個(gè)大型對(duì)象進(jìn)行響應(yīng)式處理,但只關(guān)心對(duì)象的第一層屬性變化時(shí),可以使用shallowReactive來(lái)避免深層次的響應(yīng)式處理。
import {shallowReactive} from 'vue'
export default {
name: 'App',
setup(){
let data = ({
name: 'John',
age: 25,
address: {
street: 'Main St',
city: 'New York'
}
})
let data1 = shallowReactive(data)
return {
data1
}
}
}
由于shallowReactive函數(shù)創(chuàng)建的是一個(gè)淺響應(yīng)式對(duì)象,所以當(dāng)改變data1.name
時(shí),會(huì)觸發(fā)響應(yīng)
但當(dāng)修改data1.address.street
時(shí),就不會(huì)觸發(fā)響應(yīng) (shallowReactive:只處理對(duì)象最外層屬性的響應(yīng)式)
-
shallowRef:
- shallowRef函數(shù)用于創(chuàng)建一個(gè)淺響應(yīng)式引用,它只會(huì)對(duì)值的第一層進(jìn)行響應(yīng)式處理,而不會(huì)遞歸地對(duì)嵌套的值進(jìn)行深層次響應(yīng)式處理 ===》
只處理基本數(shù)據(jù)類型的響應(yīng)式, 不進(jìn)行對(duì)象的響應(yīng)式處理
- 類似于shallowReactive,這在某些情況下可以提高性能和減少內(nèi)存消耗。
- 適用場(chǎng)景:當(dāng)需要對(duì)一個(gè)值進(jìn)行響應(yīng)式處理,但只關(guān)心值的第一層變化時(shí),可以使用shallowRef來(lái)避免深層次的響應(yīng)式處理。
- shallowRef函數(shù)用于創(chuàng)建一個(gè)淺響應(yīng)式引用,它只會(huì)對(duì)值的第一層進(jìn)行響應(yīng)式處理,而不會(huì)遞歸地對(duì)嵌套的值進(jìn)行深層次響應(yīng)式處理 ===》
<template>
{{name1}}
<button @click="name1 = '前端百草閣'">點(diǎn)我修改name</button>
<br>
{{ data1.address.street }}
<button @click="data1.address.street = '前端百草閣'">點(diǎn)我修改stree</button>
</template>
<script>
import {shallowRef} from 'vue'
export default {
name: 'App',
setup(){
let name = 'John'
let data = ({
age: 25,
address: {
street: 'Main St',
city: 'New York'
}
})
let data1 = shallowRef(data)
let name1 = shallowRef(name)
console.log(data1.value,name1.value); // 在setup中操作數(shù)據(jù)時(shí) 要加.value
return {
data1,
name1
}
}
}
</script>
這里小伙伴們注意一個(gè)點(diǎn),無(wú)論是操作數(shù)據(jù)還是使用數(shù)據(jù)都和ref、reactive一樣,ref在操作數(shù)據(jù)時(shí)要加.value才能拿到對(duì)應(yīng)的值
通過(guò)使用shallowReactive和shallowRef,可以根據(jù)具體的需求選擇性地進(jìn)行響應(yīng)式處理,避免不必要的性能開(kāi)銷。在處理大型對(duì)象或嵌套層次較深的數(shù)據(jù)時(shí),這些函數(shù)可以提供更好的性能和內(nèi)存利用率。
二、readonly 與 shallowReadonly
- readonly
- 讓一個(gè)響應(yīng)式數(shù)據(jù)變?yōu)橹蛔x的(深只讀)
- 將整個(gè)對(duì)象及其嵌套的屬性設(shè)置為只讀的場(chǎng)景,保護(hù)某些數(shù)據(jù)不被修改。
<script>
import { ref, reactive, toRefs,readonly } from "vue";
export default {
name: "deMO",
setup() {
//數(shù)據(jù)
let sum = ref(0);
let person = reactive({
name: "張三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
person = readonly(person);
sum = readonly(sum)
return {
sum,
...toRefs(person),
};
},
};
</script>
由于這里使用的是readonly深只讀,所以sum以及person的每一個(gè)屬性都無(wú)法被修改
- shallowReadonly
- 讓一個(gè)響應(yīng)式數(shù)據(jù)變?yōu)橹蛔x的(淺只讀)
- 將對(duì)象數(shù)據(jù)的第一層屬性設(shè)置為只讀
<script>
import { ref, reactive, toRefs,shallowReadonly } from "vue";
export default {
name: "deMO",
setup() {
//數(shù)據(jù)
let sum = ref(0);
let person = reactive({
name: "張三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
person = shallowReadonly(person)
sum = shallowReadonly(sum)
return {
sum,
...toRefs(person),
};
},
};
</script>
由于person設(shè)置了淺只讀,所以person中的name屬性值不能改變,但是person中的j1里的屬性是可以修改的
- 如果有一個(gè)對(duì)象數(shù)據(jù),結(jié)構(gòu)比較深, 但變化時(shí)只是外層屬性變化 ===> shallowReactive。
- 如果有一個(gè)對(duì)象數(shù)據(jù),后續(xù)功能不會(huì)修改該對(duì)象中的屬性 ===> shallowRef。
通過(guò)使用readonly和shallowReadonly,我們可以根據(jù)具體的需求選擇性地進(jìn)行保護(hù)數(shù)據(jù)的可寫(xiě)性,從而提高代碼的可靠性和安全性。
這里注意無(wú)論是深只讀還是淺只讀
都不會(huì)影響到原先的響應(yīng)式數(shù)據(jù)
,所以最好用方法返回的只讀數(shù)據(jù)覆蓋掉之前的響應(yīng)式數(shù)據(jù) ,更加安全
什么意思呢? 在進(jìn)行只讀操作后,原先的響應(yīng)式數(shù)據(jù)并不會(huì)發(fā)生變化,并且當(dāng)你再次修改這個(gè)響應(yīng)式數(shù)據(jù)時(shí),只讀的數(shù)據(jù)會(huì)跟著變化
舉個(gè)例子,大家注意看
setup() {
let car = reactive({ name: "奔馳", price: "40W" });
let car1 = readonly(car)
car.name = '寶馬'
// car1.name = '勞斯萊斯' car1的值為只讀不能修改
console.log(car1,car);
return { };
},
};
這里car1是car的只讀數(shù)據(jù),當(dāng)car的值發(fā)生變化時(shí),car1的值對(duì)應(yīng)著也會(huì)變化,但是car1的值不能直接修改
car1 的值直接修改不起作用,并且會(huì)報(bào)錯(cuò)
三、toRaw 與 markRaw
-
toRaw函數(shù):
- 作用:將一個(gè)由
reactive
生成的響應(yīng)式對(duì)象轉(zhuǎn)為普通對(duì)象 - 使用場(chǎng)景:用于讀取響應(yīng)式對(duì)象對(duì)應(yīng)的普通對(duì)象,對(duì)這個(gè)普通對(duì)象的所有操作,不會(huì)引起頁(yè)面更新。
- 作用:將一個(gè)由
<script>
import {ref,reactive,toRaw} from 'vue'
export default {
name: 'Demo',
setup(){
//數(shù)據(jù)
let person1 = ref({
name:'張三',
age:18,
job:{
j1:{
salary:20
}
}
})
let person = reactive({
name:'張三',
age:18,
job:{
j1:{
salary:20
}
}
})
const p = toRaw(person) // person是reactive生成的響應(yīng)式對(duì)象
p.age++ // 普通對(duì)象的值可以改變 但是不再引起頁(yè)面更新
console.log(p) // 轉(zhuǎn)換完后的p就是一個(gè)普通對(duì)象
const p1 = toRaw(person1.value)
p1.age++
console.log(p) // 轉(zhuǎn)換完后的p就是一個(gè)普通對(duì)象
return {
sum,
person
}
}
}
</script>
這里注意筆者為什么要寫(xiě)兩個(gè)person,不是說(shuō)toRaw的作用是把一個(gè)由reactive生成的響應(yīng)式對(duì)象轉(zhuǎn)換為一個(gè)普通對(duì)象么?
為什么這里還有一個(gè)由ref生成的響應(yīng)式對(duì)象呢
這得透過(guò)問(wèn)題看本質(zhì),ref定義一個(gè)響應(yīng)式對(duì)象內(nèi)部求助了reactive,所以person1.value實(shí)質(zhì)上也是一個(gè)Proxy對(duì)象,所以在轉(zhuǎn)換成普通對(duì)象時(shí),要toRaw(person1.value)
再注意一個(gè)問(wèn)題,大家有沒(méi)有一個(gè)疑問(wèn),我把person轉(zhuǎn)成了普通對(duì)象并且用一個(gè)p接收轉(zhuǎn)換完后的對(duì)象,那么person自己本身有變化么
實(shí)驗(yàn)才能出真知,由于好奇大家才在不停的進(jìn)步,嘗試后發(fā)現(xiàn)響應(yīng)式對(duì)象轉(zhuǎn)換為普通對(duì)象時(shí),并不會(huì)影響先前的響應(yīng)式對(duì)象,換句話說(shuō)就是person依然是響應(yīng)式對(duì)象,修改它,頁(yè)面依舊會(huì)發(fā)生變化
還有一個(gè)點(diǎn)
setup() {
let car = reactive({ name: "奔馳", price: "40W" });
let car2 = toRaw(car)
// car.name = '寶馬'
car2.name = '勞斯萊斯'
console.log(car,car2);
}
修改car 會(huì)改變car的值,修改car2的值同時(shí)car的值也會(huì)變
- markRaw:
- 作用:標(biāo)記一個(gè)對(duì)象,使其
永遠(yuǎn)不會(huì)再成為響應(yīng)式對(duì)象
。 - 應(yīng)用場(chǎng)景:
- 有些值不應(yīng)被設(shè)置為響應(yīng)式的,例如復(fù)雜的第三方類庫(kù)等。
- 當(dāng)渲染具有不可變數(shù)據(jù)源的大列表時(shí),跳過(guò)響應(yīng)式轉(zhuǎn)換可以提高性能。
響應(yīng)式追蹤和更新是一個(gè)相對(duì)開(kāi)銷較大的操作。將復(fù)雜的第三方類庫(kù)或大型對(duì)象設(shè)置為響應(yīng)式的,會(huì)導(dǎo)致每次更新時(shí)都需要深度遍歷對(duì)象并觸發(fā)更新,對(duì)性能有一定影響。如果這些值不需要在視圖中展示或參與響應(yīng)式計(jì)算,將其設(shè)置為非響應(yīng)式可以提高性能。
- 作用:標(biāo)記一個(gè)對(duì)象,使其
<script>
<script>
import { ref, reactive, toRefs, markRaw } from "vue";
export default {
name: "deMo",
setup() {
let person = reactive({
name: "張三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
let car = { name: "奔馳", price: 40 };
person.car = markRaw(car); // 將一個(gè)標(biāo)記過(guò)的對(duì)象添加到person的屬性中
person.car.price++; // 數(shù)據(jù)會(huì)變化 但是頁(yè)面不再更新(沒(méi)有響應(yīng)式)
console.log(person.car.price);
return {
person,
...toRefs(person), // 普通對(duì)象被標(biāo)記過(guò)后 再也無(wú)法變成響應(yīng)式的
};
},
};
</script>
這里注意一個(gè)點(diǎn) 如果說(shuō)person已經(jīng)是一個(gè)響應(yīng)式對(duì)象了,這時(shí)及時(shí)往他身上添加一個(gè)普通的屬性,這個(gè)屬性也具有響應(yīng)式
let car = { name: "奔馳", price: 40 };
person.car = car; // 將一個(gè)普通對(duì)象添加到person的屬性中
person.car.price++; // 數(shù)據(jù)會(huì)變化 頁(yè)面會(huì)更新(有響應(yīng)式)
console.log(person.car.price);
通過(guò)使用toRaw和markRaw,我們可以有更靈活的控制對(duì)象的響應(yīng)式特性。toRaw使我們能夠獲取響應(yīng)式對(duì)象的非響應(yīng)式原始值。markRaw則可以將對(duì)象標(biāo)記為非響應(yīng)式,避免不必要的響應(yīng)式追蹤和更新。這些工具在一些特定場(chǎng)景下提供了更好的性能和控制的選擇。
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-601715.html
總結(jié)
本文講解了vue3組合式API中的 shallowReactive 與 shallowRef、readonly 與 shallowReadonly、toRaw 與 markRaw的用法以及注意事項(xiàng),歡迎大家訂閱本系列文章,干貨滿滿!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-601715.html
到了這里,關(guān)于從Vue2到Vue3【三】——Composition API(第三章)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!