vue3使用keep-alive組件,包含動態(tài)組件使用詳解
vue3使用keep-alive組件,包含動態(tài)組件使用
組件不使用keep-alive
- Father
<template>
<div>
Father
<el-button @click="tabChange">change page</el-button>
<Child :msg="cutTab" v-if="cutTab"></Child>
<Child2 :msg="cutTab" v-else></Child2>
</div>
</template>
<script setup lang="ts" name="Father">
const cutTab = ref(false);
const tabChange = () => {
cutTab.value = !cutTab.value;
}
</script>
- Child
<template>
<div class="c1">
Child +
{{ props.msg }}
<el-input v-model="input" placeholder="Please input" />
</div>
</template>
<script setup lang="ts" name="Child">
const props = defineProps({
msg: {
type: Boolean,
default: false,
},
})
const input = ref('')
</script>
- Child2
<template>
<div class="c2">
Child2 +
{{ props.msg }}
<el-input v-model="input" placeholder="Please input" />
</div>
</template>
<script setup lang="ts" name="Child2">
const props = defineProps({
msg: {
type: Boolean,
default: false,
},
})
const input = ref('')
</script>


組件中使用
include:包含exclude:排除
v-if切換
<keep-alive>
<Child :msg="cutTab" v-if="cutTab"></Child>
<Child2 :msg="cutTab" v-else></Child2>
</keep-alive>
<keep-alive include="Child2">
<Child :msg="cutTab" v-if="cutTab"></Child>
<Child2 :msg="cutTab" v-else></Child2>
</keep-alive>



component動態(tài)組件切換
因注釋導(dǎo)致的意外錯誤
<KeepAlive> expects exactly one child component

<keep-alive include="Child2">
<!-- <Child :msg="cutTab" v-if="cutTab"></Child>
<Child2 :msg="cutTab" v-else></Child2> -->
<component :is="com"></component>
</keep-alive>
keep-alive組件內(nèi)不要使用注釋,會被解析為子節(jié)點(diǎn)
- 添加div進(jìn)行包裹
<keep-alive include="Child2">
<div>
<!-- <Child :msg="cutTab" v-if="cutTab"></Child>
<Child2 :msg="cutTab" v-else></Child2> -->
<component :is="com"></component>s
</div>
</keep-alive>
- 移除注釋
<keep-alive include="Child2">
<component :is="com"></component>
</keep-alive>
動態(tài)組件的使用
[Vue warn]: Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with 'markRaw' or using 'shallowRef' instead of 'ref'.

在 Vue 3 中,如果用 ref 或 reactive 將一個組件包裝成響應(yīng)式對象,可能會引發(fā)不必要的性能開銷。因?yàn)檫@會使 Vue 嘗試去追蹤組件的變化,而實(shí)際上組件實(shí)例并不需要被追蹤。組件本身不應(yīng)該是響應(yīng)式的,只有它的 props 和 state 才應(yīng)該是響應(yīng)式的。
所以,當(dāng)需要引用一個組件時,應(yīng)該使用 shallowRef或者 markRaw,這樣可以避免將整個組件變成響應(yīng)式的,只會跟蹤引用的變化
- 使用markRaw
const com = ref(markRaw(Child2));
const comChange = () => {
if(com.value === Child2){
com.value = markRaw(Child);
}else{
com.value = markRaw(Child2);
}
}
- 使用shallowRef
const com = shallowRef(Child2);
const comChange = () => {
if(com.value === Child2){
com.value = Child;
}else{
com.value = Child2;
}
}
完整示例
<template>
<div>
Father
<el-button @click="comChange">change component</el-button>
<keep-alive include="Child2">
<component :is="com"></component>
</keep-alive>
</div>
</template>
<script setup lang="ts" name="Father">
import Child from "@/views/Child.vue";
import Child2 from "@/views/Child2.vue";
const cutTab = ref(false);
const com = ref(markRaw(Child2));
const comChange = () => {
if(com.value === Child2){
com.value = markRaw(Child);
}else{
com.value = markRaw(Child2);
}
}
</script>
可以看到只有Child2組件是有緩存的,Child是有銷毀和生成的

路由不使用keep-alive
- 組件
<template>
<div>
Father
<div class="nav">
<router-link to="/Father/Child">去Child頁面</router-link>
<el-divider direction="vertical" />
<router-link to="/Father/Child2">去Child2頁面</router-link>
</div>
<router-view></router-view>
</div>
</template>
- 路由index.ts
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
const routes = [
{
path: '/Father',
name: 'Father',
component: () => import('@/views/Father.vue'),
children: [
{
path: 'Child',
name: 'Child',
component: () => import('@/views/Child.vue'),
},
{
path: 'Child2',
name: 'Child2',
component: () => import('@/views/Child2.vue'),
}
],
},
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router

路由中使用
Vue Router 4(與 Vue 3 配套的路由庫)引入了一個新的 API 來實(shí)現(xiàn)路由級別的 <keep-alive>。這就是 <router-view> 組件的 v-slot API
- 需要注意的是
v-if不要加在keep-alive上,會直接銷毀keep-alive,需要加在component上 - 實(shí)現(xiàn)頁面部分刷新,頁面進(jìn)入時執(zhí)行的生命周期為:
created->mounted->activated
<template>
<div>
Father
<div class="nav">
<router-link to="/Father/Child">去Child頁面</router-link>
<el-divider direction="vertical" />
<router-link to="/Father/Child2">去Child2頁面</router-link>
</div>
<router-view v-slot="{ Component }">
<keep-alive >
<component :is="Component" v-if="$route.meta.keepAlive"/>
</keep-alive>
<component :is="Component" v-if="!$route.meta.keepAlive"/>
</router-view>
</div>
</template>
路由index.ts
在對應(yīng)的路由上添加meta屬性來設(shè)置頁面是否要使用緩存
...
const routes = [
{
path: '/Father',
name: 'Father',
component: () => import('@/views/Father.vue'),
children: [
{
path: 'Child',
name: 'Child',
component: () => import('@/views/Child.vue'),
},
{
path: 'Child2',
name: 'Child2',
meta: {
keepAlive: true, // 需要被keep-alive
},
component: () => import('@/views/Child2.vue'),
}
],
},
]
...

keep-alive生命周期
有keep-alive組件會多出兩個生命周期,分別在mounted之后和unMounted之前
onActivated(() => {
console.log('Component is activated')
})
onDeactivated(() => {
console.log('Component is deactivated')
})


總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vite項目的根目錄中的env.d.ts類型聲明文件里要寫什么
這篇文章主要介紹了vite項目的根目錄中的env.d.ts類型聲明文件里要寫什么,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
使用Vue與Firebase構(gòu)建實(shí)時聊天應(yīng)用的示例代碼
隨著互聯(lián)網(wǎng)通訊技術(shù)的不斷進(jìn)步,實(shí)時聊天應(yīng)用現(xiàn)在已成為我們?nèi)粘I钪胁豢苫蛉钡囊徊糠?無論是社交媒體平臺、工作溝通工具還是客戶支持系統(tǒng),實(shí)時聊天都在不斷被需求,今天,我們將介紹如何使用Vue.js與Firebase來構(gòu)建一個簡單而強(qiáng)大的實(shí)時聊天應(yīng)用,需要的朋友可以參考下2024-11-11
如何使用el-table+el-tree+el-select動態(tài)選擇對應(yīng)值
小編在做需求時,遇到了在el-table表格中加入多條數(shù)據(jù),并且每條數(shù)據(jù)要通過el-select來選取相應(yīng)的值,做到動態(tài)選擇,下面這篇文章主要給大家介紹了關(guān)于如何使用el-table+el-tree+el-select動態(tài)選擇對應(yīng)值的相關(guān)資料,需要的朋友可以參考下2023-01-01
一步一步實(shí)現(xiàn)Vue的響應(yīng)式(對象觀測)
這篇文章主要介紹了一步一步實(shí)現(xiàn)Vue的響應(yīng)式(對象觀測),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
vue中實(shí)現(xiàn)div可編輯并插入指定元素與樣式
這篇文章主要給大家介紹了關(guān)于vue中實(shí)現(xiàn)div可編輯并插入指定元素與樣式的相關(guān)資料,文中通過代碼以及圖文將實(shí)現(xiàn)的方法介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09
vue自定義密碼輸入框解決瀏覽器自動填充密碼的問題(最新方法)
這篇文章主要介紹了vue自定義密碼輸入框解決瀏覽器自動填充密碼的問題,通過將密碼輸入框的type設(shè)置為text,修改樣式上的顯示,來實(shí)現(xiàn)既可以讓瀏覽器不自動填充密碼,又可以隱藏密碼的效果,需要的朋友可以參考下2023-04-04
vuejs實(shí)現(xiàn)折疊面板展開收縮動畫效果
這篇文章主要介紹了vuejs實(shí)現(xiàn)折疊面板展開收縮動畫效果,文中通過代碼給大家分享兩種情況介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2018-09-09

