vue緩存之keep-alive的理解和應(yīng)用詳解
官方解釋?zhuān)?/p>
<keep-alive> 包裹動(dòng)態(tài)組件時(shí),會(huì)緩存不活動(dòng)的組件實(shí)例,而不是銷(xiāo)毀它們。和 <transition> 相似,<keep-alive> 是一個(gè)抽象組件:它自身不會(huì)渲染一個(gè) DOM 元素,也不會(huì)出現(xiàn)在組件的父組件鏈中。
當(dāng)組件在 <keep-alive> 內(nèi)被切換,它的 activated 和 deactivated 這兩個(gè)生命周期鉤子函數(shù)將會(huì)被對(duì)應(yīng)執(zhí)行。
主要用于保留組件狀態(tài)或避免重新渲染。
keep-alive 是 Vue 的內(nèi)置組件,在組件切換過(guò)程中將狀態(tài)保留在內(nèi)存中,等再次訪問(wèn)的時(shí)候,還保持著離開(kāi)之前的所有狀態(tài),而不是重新初始化。也就是所謂的組件緩存。
我們知道,使用路由vue-router切換組件的時(shí)候是不保存狀態(tài)的,它進(jìn)行router.push()或router.push()或router.replace()的時(shí)候,舊組件會(huì)被銷(xiāo)毀,新組件會(huì)被新建,然后走一遍完整的生命周期。所以緩存經(jīng)常與router-view一起出現(xiàn):
<keep-alive> <router-view /> <!-- 所有路徑匹配到的視圖組件都會(huì)被緩存 --></keep-alive>
被包含在 keep-alive 中創(chuàng)建的組件,會(huì)多出兩個(gè)生命周期的鉤子: activated 與 deactivated:
1. activated:在 keep-alive 組件激活時(shí)調(diào)用2. deactivated:在 keep-alive 組件停用時(shí)調(diào)用
注意: 只有組件被 keep-alive 包裹時(shí),這兩個(gè)生命周期函數(shù)才會(huì)被調(diào)用。這兩個(gè)鉤子在服務(wù)器端渲染期間不被調(diào)用。
應(yīng)用場(chǎng)景:
官網(wǎng)有一個(gè)多標(biāo)簽界面的例子,介紹的還是蠻詳細(xì)的。
我們?cè)趯?shí)際開(kāi)發(fā)項(xiàng)目中會(huì)有一些需求,比如跳轉(zhuǎn)到詳情頁(yè)面時(shí),需要保持列表頁(yè)的滾動(dòng)條的位置,返回的時(shí)候依然在這個(gè)位置,這樣可以提高用戶體驗(yàn),這個(gè)時(shí)候就可以使用緩存組件 keep-alive 來(lái)解決。
設(shè)置了 keep-alive 緩存的組件,會(huì)多出兩個(gè)生命周期鉤子:
首次進(jìn)入組件時(shí):beforeRouteEnter > beforeCreate > created > mounted > activated > ... ... > beforeRouteLeave > deactivated 再次進(jìn)入組件時(shí):beforeRouteEnter > activated > ... ... > beforeRouteLeave > deactivated可以看到,緩存的組件中 activated 鉤子函數(shù)每次都會(huì)觸發(fā),所以可以通過(guò)這個(gè)鉤子判斷,當(dāng)前組件時(shí)需要使用緩存的數(shù)據(jù)還是重新調(diào)用接口加載數(shù)據(jù)。如果未使用keep-alive 組件,則在頁(yè)面回退時(shí)會(huì)重新渲染頁(yè)面,首次進(jìn)入組件的一系列生命周期也會(huì)一一被觸發(fā)。
離開(kāi)組件時(shí),使用了 keep-alive 不會(huì)調(diào)用 beforeDestroy 和 destroyed 鉤子,因?yàn)榻M件沒(méi)被銷(xiāo)毀,被緩存起來(lái)了。所以 deactivated 這個(gè)鉤子可以看作是 beforeDestroy 和 destroyed 的代替,緩存組件銷(xiāo)毀的時(shí)候要做的一些操作可以放在這個(gè)里面。
需求案例
最近項(xiàng)目中碰到需要緩存的場(chǎng)景,主要還是列表頁(yè)到詳情頁(yè)的跳轉(zhuǎn),但列表頁(yè)存在多級(jí)關(guān)系,具體需求如下:
初次進(jìn)入此頁(yè)面,默認(rèn)展示左側(cè)的樹(shù)形結(jié)構(gòu)菜單,點(diǎn)擊某一菜單,右側(cè)加載該菜單相應(yīng)的數(shù)據(jù)列表,由列表進(jìn)入詳情內(nèi)頁(yè),然后再返回該頁(yè)面,希望該頁(yè)面保留了用戶之前選擇的樹(shù)形菜單及數(shù)據(jù)列表。若從其他頁(yè)面進(jìn)入此頁(yè)面,則不需要緩存。
案例實(shí)踐
思路:結(jié)合 router 中設(shè)置 meta 信息,緩存列表頁(yè)。1. 設(shè)置路由的 meta 信息
const List = () => import(/* webpackChunkName: 'list' */ ’../pages/List.vue’)const Detail = () => import(/* webpackChunkName: 'detail' */ ’../pages/Detail.vue’){ path: ’list’, name: ’list’, component: List, meta: { title: ’列表’, keepAlive: true, //需要緩存 isKeep: false }},{ path: ’dist’, name: ’detail’, component: Detail}
2. 修改渲染匹配視圖組件 router-view(一般是 app.vue 文件,根據(jù)實(shí)際需求會(huì)不一樣)
<div class='container'> <keep-alive> <!-- 需要緩存的視圖組件 --> <router-view v-if='$route.meta.keepAlive'></router-view> </keep-alive> <!-- 不需要緩存的視圖組件 --> <router-view v-if='!$route.meta.keepAlive'></router-view></div>
也可以使用 keep-alive 組件的 include/exclude 屬性,include 表示要緩存的組件名(定義時(shí)的 name 屬性),而 exclude 相反,匹配到的組件不會(huì)被緩存。
<div class='container'> <keep-alive include='list'> <router-view></router-view> </keep-alive></div>
3. 在需要緩存的頁(yè)面中,通過(guò)導(dǎo)航守衛(wèi) beforeRouteEnter 和 activated 鉤子判斷使用緩存還是重新渲染
beforeRouteEnter (to, from, next) { // 只在詳情返回時(shí)做緩存 if (from.name === ’detail’) { to.meta.isKeep = true } else { to.meta.isKeep = false } next()},activated () { if(this.$route.meta.isKeep) { // 詳情返回,取緩存數(shù)據(jù) } else { // 重新渲染,在這里調(diào)用加載請(qǐng)求 }}
此處 beforeRouteEnter 鉤子也可以使用 watch 屬性監(jiān)聽(tīng)路由的變化:
watch: { $route(to, from) { //通過(guò)to/from.path判斷是否是需要緩存的路徑然后添加邏輯 }}
問(wèn)題:
從詳情返回列表時(shí)正常,但當(dāng)用戶在詳情頁(yè)按 F5 刷新之后,再返回列表就不能保留離開(kāi)之前的狀態(tài)了,因?yàn)檫@時(shí)頁(yè)面重載了。
解決辦法:
在離開(kāi)當(dāng)前之前,將信息儲(chǔ)存在 localStorage 中,當(dāng)詳情數(shù)據(jù)刷新后,手動(dòng)觸發(fā)加載請(qǐng)求。
到此這篇關(guān)于vue緩存之keep-alive的理解和應(yīng)用詳解的文章就介紹到這了,更多相關(guān)vue keep-alive內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. XML入門(mén)的常見(jiàn)問(wèn)題(一)2. html小技巧之td,div標(biāo)簽里內(nèi)容不換行3. PHP字符串前后字符或空格刪除方法介紹4. AspNetCore&MassTransit Courier實(shí)現(xiàn)分布式事務(wù)的詳細(xì)過(guò)程5. jsp cookie+session實(shí)現(xiàn)簡(jiǎn)易自動(dòng)登錄6. css進(jìn)階學(xué)習(xí) 選擇符7. 將properties文件的配置設(shè)置為整個(gè)Web應(yīng)用的全局變量實(shí)現(xiàn)方法8. 解析原生JS getComputedStyle9. Echarts通過(guò)dataset數(shù)據(jù)集實(shí)現(xiàn)創(chuàng)建單軸散點(diǎn)圖10. nestjs實(shí)現(xiàn)圖形校驗(yàn)和單點(diǎn)登錄的示例代碼
