三、其它 Composition API
1.shallowReactive 與 shallowRef
- shallowReactive:只處理對象最外層屬性的響應(yīng)式(淺響應(yīng)式)。
- shallowRef:只處理基本數(shù)據(jù)類型的響應(yīng)式, 不進(jìn)行對象的響應(yīng)式處理。
- 什么時候使用?
- 如果有一個對象數(shù)據(jù),結(jié)構(gòu)比較深, 但變化時只是外層屬性變化 ===> shallowReactive。
- 如果有一個對象數(shù)據(jù),后續(xù)功能不會修改該對象中的屬性,而是生新的對象來替換 ===> shallowRef。
2.readonly 與 shallowReadonly
- readonly: 讓一個響應(yīng)式數(shù)據(jù)變?yōu)橹蛔x的(深只讀)。
- shallowReadonly:讓一個響應(yīng)式數(shù)據(jù)變?yōu)橹蛔x的(淺只讀)。
- 應(yīng)用場景: 不希望數(shù)據(jù)被修改時。
3.toRaw 與 markRaw
- toRaw:
- 作用:將一個由
reactive生成的 響應(yīng)式對象 轉(zhuǎn)為 普通對象。 - 使用場景:用于讀取響應(yīng)式對象對應(yīng)的普通對象,對這個普通對象的所有操作,不會引起頁面更新。
- 作用:將一個由
- markRaw:
- 作用:標(biāo)記一個對象,使其永遠(yuǎn)不會再成為響應(yīng)式對象。
- 應(yīng)用場景:
- 有些值不應(yīng)被設(shè)置為響應(yīng)式的,例如復(fù)雜的第三方類庫等。
- 當(dāng)渲染具有不可變數(shù)據(jù)源的大列表時,跳過響應(yīng)式轉(zhuǎn)換可以提高性能。
4.customRef
- 作用:創(chuàng)建一個自定義的 ref,并對其依賴項跟蹤和更新觸發(fā)進(jìn)行顯式控制。
- 實現(xiàn)防抖效果:
<template>
<input type="text" v-model="keyword">
<h3>{{keyword}}</h3>
</template>
<script>
import {ref,customRef} from 'vue'
export default {
name:'Demo',
setup(){
// let keyword = ref('hello') //使用Vue準(zhǔn)備好的內(nèi)置ref
//自定義一個myRef
function myRef(value,delay){
let timer
//通過customRef去實現(xiàn)自定義
return customRef((track,trigger)=>{
return{
get(){
track() //告訴Vue這個value值是需要被“追蹤”的
return value
},
set(newValue){
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue
trigger() //告訴Vue去更新界面
},delay)
}
}
})
}
let keyword = myRef('hello',500) //使用程序員自定義的ref
return {
keyword
}
}
}
</script>
5.provide 與 inject

- 作用:實現(xiàn)『祖先與后代』組件間通信
- 套路:父組件有一個
provide選項來提供數(shù)據(jù),后代組件有一個inject選項來開始使用這些數(shù)據(jù) - 具體寫法:
1.祖先組件中:
2.后代組件中:setup(){ ...... let car = reactive({name:'奔馳',price:'40萬'}) provide('car',car) ...... }setup(props,context){ ...... const car = inject('car') return {car} ...... }
6.響應(yīng)式數(shù)據(jù)的判斷
- isRef: 檢查一個值是否為一個 ref 對象
- isReactive: 檢查一個對象是否是由
reactive創(chuàng)建的響應(yīng)式代理 - isReadonly: 檢查一個對象是否是由
readonly創(chuàng)建的只讀代理 - isProxy: 檢查一個對象是否是由
reactive或者readonly方法創(chuàng)建的代理
四、Composition API 的優(yōu)勢
1.Options API 存在的問題
使用傳統(tǒng)OptionsAPI中,新增或者修改一個需求,就需要分別在data,methods,computed里修改 。
圖1 OptionsAPI
圖2 OptionsAPI
2.Composition API 的優(yōu)勢
我們可以更加優(yōu)雅的組織我們的代碼,函數(shù)。讓相關(guān)功能的代碼更加有序的組織在一起。
圖1 Composition API
圖2 Composition API
五、新的組件
1.Fragment
- 在Vue2中: 組件必須有一個根標(biāo)簽
- 在Vue3中: 組件可以沒有根標(biāo)簽, 內(nèi)部會將多個標(biāo)簽包含在一個Fragment虛擬元素中
- 好處: 減少標(biāo)簽層級, 減小內(nèi)存占用
2.Teleport
- 什么是Teleport?——
Teleport是一種能夠?qū)⑽覀兊?組件html結(jié)構(gòu) 移動到指定位置的技術(shù)。
<teleport to="移動位置">
<div v-if="isShow" class="mask">
<div class="dialog">
<h3>我是一個彈窗</h3>
<button @click="isShow = false">關(guān)閉彈窗</button>
</div>
</div>
</teleport>
3.Suspense
- 等待異步組件時渲染一些額外內(nèi)容,讓應(yīng)用有更好的用戶體驗
- 使用步驟:
- 異步引入組件
import {defineAsyncComponent} from 'vue' const Child = defineAsyncComponent(()=>import('./components/Child.vue'))- 使用
Suspense包裹組件,并配置好default與fallback
<template> <div class="app"> <h3>我是App組件</h3> <Suspense> <template v-slot:default> <Child/> </template> <template v-slot:fallback> <h3>加載中.....</h3> </template> </Suspense> </div> </template>
六、其他
1.全局API的轉(zhuǎn)移
- Vue 2.x 有許多全局 API 和配置。
- 例如:注冊全局組件、注冊全局指令等。
//注冊全局組件
Vue.component('MyButton', {
data: () => ({
count: 0
}),
template: '<button @click="count++">Clicked {{ count }} times.</button>'
})
//注冊全局指令
Vue.directive('focus', {
inserted: el => el.focus()
}
Vue3.0中對這些API做出了調(diào)整:
- 將全局的API,即:
Vue.xxx調(diào)整到應(yīng)用實例(app)上2.x 全局 API( Vue)3.x 實例 API ( app)Vue.config.xxxx app.config.xxxx Vue.config.productionTip 移除 Vue.component app.component Vue.directive app.directive Vue.mixin app.mixin Vue.use app.use Vue.prototype app.config.globalProperties
2.其他改變
- data選項應(yīng)始終被聲明為一個函數(shù)。
- 過度類名的更改:
- Vue2.x寫法
.v-enter, .v-leave-to { opacity: 0; } .v-leave, .v-enter-to { opacity: 1; }- Vue3.x寫法
.v-enter-from, .v-leave-to { opacity: 0; } .v-leave-from, .v-enter-to { opacity: 1; } - 移除keyCode作為 v-on 的修飾符,同時也不再支持
config.keyCodes - 移除
v-on.native修飾符- 父組件中綁定事件
<my-component v-on:close="handleComponentEvent" v-on:click="handleNativeClickEvent" />- 子組件中聲明自定義事件
<script> export default { emits: ['close'] 沒聲明的click事件是原生事件 } </script> - 移除過濾器(filter)
過濾器雖然這看起來很方便,但它需要一個自定義語法,打破大括號內(nèi)表達(dá)式是 “只是 JavaScript” 的假設(shè),這不僅有學(xué)習(xí)成本,而且有實現(xiàn)成本!建議用方法調(diào)用或計算屬性去替換過濾器。
- ......