樂清網(wǎng)站設(shè)計公司哪家好百度 營銷中心
一、toRef函數(shù)
在 Vue 3.0 中,引入了一種新的響應(yīng)式 API,即
toRef
。toRef
函數(shù)可以將一個普通值轉(zhuǎn)換為響應(yīng)式引用類型,這樣就可以在模板中直接使用這個響應(yīng)式引用類型的屬性,并且當(dāng)該屬性發(fā)生變化時,視圖會自動更新。
<template><div><h2>年齡:{{ age }}</h2><h2>原值:{{person.age }}</h2><button @click="age++;console.log(age)">年齡增加</button></div>
</template><script>
import { reactive} from 'vue';export default {name: 'TodoList',setup() {// 使用 ref 創(chuàng)建響應(yīng)式數(shù)據(jù)const person = reactive({name: 'JingYu',age: 18,})// 暴露數(shù)據(jù)和方法給模板使用return {age:person.age,person,};},
};
</script>
通過控制臺打印輸出的內(nèi)容和頁面的變化,我們可以觀察到,age的值一直在變化,但其不是響應(yīng)式的,所以頁面沒有隨著值的變化而更新視圖。這是因為這種寫法就好比我們定義了一個新的變量,將person.age的值18賦值給這個變量。但這個變量并不是響應(yīng)式的。
這時我們就可以通過toRef
將其轉(zhuǎn)換為響應(yīng)式的
const person = reactive({name: 'JingYu',age: 18,})// 暴露數(shù)據(jù)和方法給模板使用let age=toRef(person,'age')console.log(age)return {age,person,};
細(xì)心地同學(xué)可能從上面的代碼中注意到了一點,我在頁面中還顯示了一個person.age
的值。
<div><h2>年齡:{{ age }}</h2><h2>原值:{{person.age }}</h2><button @click="age++;console.log(age)">年齡增加</button></div>
為什么要展示它的值呢,看了將person中age屬性單獨轉(zhuǎn)換成一個單獨的響應(yīng)式引用之后,你就會發(fā)現(xiàn),頁面展示的兩個值都會隨之改變。
如果你不小心寫成了這種形式
let age=toRef(person.age)
你就會驚奇的發(fā)現(xiàn),頁面展示的person.age不會隨之改變了.
這里需要注意一下兩種寫法的區(qū)別:
1.當(dāng)你使用
toRef(person, 'age')
時,你是在告訴Vue你希望將person
對象的age
屬性轉(zhuǎn)換為一個單獨的響應(yīng)式引用。這意味著當(dāng)person.age
的值發(fā)生變化時,引用的值也會相應(yīng)地更新。
2.toRef(person.age)
是將person.age
直接轉(zhuǎn)換為響應(yīng)式引用,而不是從person
對象中獲取對age
屬性的引用。這意味著當(dāng)你修改person.age
的值時,引用的值不會自動更新。
二、toRefs函數(shù)
torefs
和toRef
的作用是一樣的,只不過toRefs
是將一個對象的所有屬性都變?yōu)閱为毜捻憫?yīng)式。
setup() {// 使用 ref 創(chuàng)建響應(yīng)式數(shù)據(jù)const person = reactive({name: 'JingYu',age: 18,})// 暴露數(shù)據(jù)和方法給模板使用return {...toRefs(person)};},
通過使用擴展運算符將person
對象的所有屬性展開返回。成功實現(xiàn)單個屬性的響應(yīng)式。
三、shallowReactive 與 shallowRef
shallow是淺的、淺顯的意思。
顧名思義:
shallowReactive
:只處理對象最外層屬性的響應(yīng)式(淺響應(yīng)式)
<h2>年齡{{ person.age }}</h2><h2>薪資{{ person.job.salary }}</h2><button @click="person.age++;console.log(person.age,'---')">年齡增加</button><button @click="person.job.salary++;console.log(person.job.salary)">薪資增加</button>const person = shallowReactive({name: 'JingYu',age: 18,job:{name:'前端開發(fā)',salary:8}})
我們可以觀察到年齡是響應(yīng)式的,而第二層的屬性薪資就不是響應(yīng)式的了。
shallowRef
:只處理基本數(shù)據(jù)類型的響應(yīng)式, 不進(jìn)行對象的響應(yīng)式處理。
<h2>年齡{{ person.age }}</h2><button @click="person.age++;console.log(person.age,'---')">年齡增加</button>const person = shallowRef({name: 'JingYu',age: 18,})
雖然person.age
的值改變了,但數(shù)據(jù)并不是響應(yīng)式的,所以頁面視圖沒有更新。
- 使用場景
1.如果有一個對象數(shù)據(jù),結(jié)構(gòu)比較深, 但變化時只是外層屬性變化 ===> shallowReactive。
2.如果有一個對象數(shù)據(jù),后續(xù)功能不會修改該對象中的屬性,而是用新的對象來替換 ===> shallowRef。
解釋一下這句話:
<h2>年齡{{ person.age }}</h2><button @click="person={age:20}">年齡改變</button>
此時點擊按鈕頁面會變?yōu)?0,因為我們改變的不是x里面的屬性,而是將整個person對象重新賦值,person是響應(yīng)式。的。
四、readonly 與 shallowReadonly
readonly
: 讓一個響應(yīng)式數(shù)據(jù)變?yōu)橹蛔x的(深只讀)。
如果使用readonly修飾對象person,所有的屬性都不能修改了。當(dāng)你修改時控制臺還會輸出警告.
<template><h2>姓名:{{name}}</h2><h2>年齡:{{age}}</h2><h2>薪資:{{job.j1.salary}}K</h2><button @click="name+='~'">修改姓名</button><button @click="age++">增長年齡</button><button @click="job.j1.salary++">漲薪</button>
</template><script>import {reactive,toRefs,readonly} from 'vue'export default {name: 'HelloWorld',setup(){//數(shù)據(jù)let person = reactive({name:'張三',age:18,job:{j1:{salary:20}}})person = readonly(person)//返回一個對象(常用)return {...toRefs(person)}}}
</script>
如果使用shallowReadonly修飾對象person,只有最外層的不能修改了。salary還是可以修改的。
<template><h2>姓名:{{name}}</h2><h2>年齡:{{age}}</h2><h2>薪資:{{job.j1.salary}}K</h2><button @click="name+='~'">修改姓名</button><button @click="age++">增長年齡</button><button @click="job.j1.salary++">漲薪</button>
</template><script>import {reactive,toRefs,shallowReadonly} from 'vue'export default {name: 'HelloWorld',setup(){//數(shù)據(jù)let person = reactive({name:'張三',age:18,job:{j1:{salary:20}}})person = shallowReadonly(person)//返回一個對象(常用)return {...toRefs(person)}}}
</script>
五、toRaw 與 markRaw
toRaw
是一個用于將響應(yīng)式對象轉(zhuǎn)換為其原始非響應(yīng)式版本的函數(shù)。
toRaw
函數(shù)接受一個響應(yīng)式對象作為參數(shù),并返回該對象的原始非響應(yīng)式版本。它實際上返回了一個指向原始對象的引用,而不是創(chuàng)建一個新的對象。
import { reactive, toRaw } from 'vue'
const originalObj = { foo: 'bar' }
const reactiveObj = reactive(originalObj)
console.log(reactiveObj.foo) // 輸出 "bar"
const rawObj = toRaw(reactiveObj)
rawObj.foo = 'baz' // 修改原始對象
console.log(reactiveObj.foo) // 輸出 "baz"
markRaw
是Vue3中用于標(biāo)記一個對象,使其永遠(yuǎn)不會轉(zhuǎn)換為響應(yīng)式對象的函數(shù)。
有些值不應(yīng)被設(shè)置為響應(yīng)式的,例如復(fù)雜的第三方類庫或Vue組件對象。在這種情況下,我們可以使用markRaw
函數(shù)。
import { reactive, markRaw } from 'vue'
const originalObj = { foo: 'bar' }
const reactiveObj = reactive(originalObj)
console.log(reactiveObj.foo) // 輸出 "bar"
const rawObj = markRaw(originalObj)
console.log(isReactive(reactiveObj)) // 輸出 "true"
console.log(isReactive(rawObj)) // 輸出 "false"
// 嘗試將rawObj轉(zhuǎn)換為響應(yīng)式對象
const reactiveRawObj = reactive(rawObj)
console.log(isReactive(reactiveRawObj)) // 輸出 "false"
在上面的示例中,我們首先使用reactive
函數(shù)將originalObj
轉(zhuǎn)換為一個響應(yīng)式對象reactiveObj
。然后,我們使用markRaw
函數(shù)將originalObj
轉(zhuǎn)換為其非響應(yīng)式版本rawObj
。我們使用isReactive
函數(shù)驗證了reactiveObj
是響應(yīng)式對象,而rawObj
不是。最后,我們嘗試將rawObj
轉(zhuǎn)換為響應(yīng)式對象,但是通過isReactive
函數(shù)驗證后發(fā)現(xiàn),轉(zhuǎn)換并未生效。
六、provide 與 inject
在Vue 3中,provide
和inject
是用于跨層級組件通信的兩種方法。
provide
方法允許父組件向下傳遞數(shù)據(jù)給子組件。provide()
接受兩個參數(shù):第一個參數(shù)是要注入的 key,可以是一個字符串或者一個 symbol,第二個參數(shù)是要注入的值。
inject
方法允許子組件從父組件中獲取傳遞的數(shù)據(jù)。它接收兩個參數(shù):一個是需要注入的鍵值,另一個是默認(rèn)值。如果父組件沒有提供該鍵值,則inject
方法將返回默認(rèn)值。
具體用法
祖組件中:
setup(){......let car = reactive({name:'奔馳',price:'40萬'})provide('car',car)......
}
后代組件:
setup(props,context){......const car = inject('car')return {car}......
}
響應(yīng)式數(shù)據(jù)的判斷
- isRef: 檢查一個值是否為一個 ref 對象
- isReactive: 檢查一個對象是否是由
reactive
創(chuàng)建的響應(yīng)式代理 - isReadonly: 檢查一個對象是否是由
readonly
創(chuàng)建的只讀代理 - isProxy: 檢查一個對象是否是由
reactive
或者readonly
方法創(chuàng)建的代理