keep-alive
有時候我們不希望組件被重新渲染影響使用體驗裙士;或者處于性能考慮,避免多次重復(fù)渲染降低性能管毙。而是希望組件可以緩存下來,維持當(dāng)前的狀態(tài)腿椎。這時候就可以用到keep-alive組件。
官網(wǎng)解釋:<keep-alive> 包裹動態(tài)組件時夭咬,會緩存不活動的組件實例啃炸,而不是銷毀它們。和 <transition> 相似卓舵,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素南用,也不會出現(xiàn)在父組件鏈中。 當(dāng)組件在 <keep-alive> 內(nèi)被切換,它的 activated 和 deactivated 這兩個生命周期鉤子函數(shù)將會被對應(yīng)執(zhí)行裹虫。 在 2.2.0 及其更高版本中肿嘲,activated 和 deactivated 將會在 <keep-alive> 樹內(nèi)的所有嵌套組件中觸發(fā)。 主要用于保留組件狀態(tài)或避免重新渲染
應(yīng)用場景
如果未使用keep-alive組件恒界,則在頁面回退時仍然會重新渲染頁面睦刃,觸發(fā)created鉤子,使用體驗不好十酣。 在以下場景中使用keep-alive組件會顯著提高用戶體驗,菜單存在多級關(guān)系际长,多見于列表頁+詳情頁的場景如:
商品列表頁點擊商品跳轉(zhuǎn)到商品詳情耸采,返回后仍顯示原有信息
訂單列表跳轉(zhuǎn)到訂單詳情,返回工育,等等場景虾宇。
keep-alive的生命周期
初次進(jìn)入時:created > mounted > activated;退出后觸發(fā) deactivated
再次進(jìn)入:會觸發(fā) activated如绸;事件掛載的方法等嘱朽,只執(zhí)行一次的放在 mounted 中;組件每次進(jìn)去執(zhí)行的方法放在 activated 中
項目實踐
1.更改App.vue
<div id="app" class='wrapper'>
<keep-alive>
<!-- 需要緩存的視圖組件 -->
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<!-- 不需要緩存的視圖組件 -->
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
2.在路由中設(shè)置keepAlive
{
path: 'list',
name: 'itemList', // 商品管理
component (resolve) {
require(['@/pages/item/list'], resolve)
},
meta: {
keepAlive: true,
title: '商品管理'
}
}
3.更改 beforeEach鉤子
這一步是為了清空無用的頁面緩存怔接。 假設(shè)現(xiàn)在A搪泳、B兩個頁面都開啟的緩存:
- 若第一次進(jìn)入A頁面后退出,再次進(jìn)入頁面時扼脐,頁面不會刷新岸军。這和目前的業(yè)務(wù)邏輯不符。我們想要的結(jié)果是A頁面前進(jìn)后返回瓦侮,頁面保持不變艰赞,而不是退出后重新進(jìn)入保持不變。
- 在進(jìn)入過A頁面后進(jìn)入B頁面肚吏,經(jīng)過測試后發(fā)現(xiàn)方妖,B頁面竟然會顯示A頁面的緩存,盡管url已經(jīng)改變
為了解決這個問題罚攀,需要判斷頁面是在前進(jìn)還是后退党觅。 在beforeEach鉤子添加代碼:
let toDepth = to.path.split('/').length
let fromDepth = from.path.split('/').length
if (toDepth < fromDepth) {
// console.log('back...')
from.meta.keepAlive = false
to.meta.keepAlive = true
}
記錄頁面滾動位置
keep-alive并不會記錄頁面的滾動位置,所以我們在跳轉(zhuǎn)時需要記錄當(dāng)前的滾動位置坞生,在觸發(fā)activated鉤子時重新定位到原有位置仔役。 具體設(shè)計思路:
- 在deactivated鉤子中記錄當(dāng)前滾動位置,使用localStorage:
deactivated () {
window.localStorage.setItem(this.key, JSON.stringify({
listScrollTop: this.scrollTop
}))
}
- 在activated鉤子中滾動:
this.cacheData = window.localStorage.getItem(this.key) 是己?JSON.parse(window.localStorage.getItem(this.key)) : null
$('.sidebar-item').scrollTop(this.cacheData.listScrollTop)
歡迎在下方留言討論又兵,更多內(nèi)容可搜索關(guān)注微信公眾號“一郭鮮”,小郭與你一起成長!