vuex + keep-alive實(shí)現(xiàn)tab標(biāo)簽頁面緩存功能
在開發(fā)很多管理系統(tǒng)過程之中,常遇到這種需求,需要對(duì)打開路由頁面進(jìn)行緩存,然后在系統(tǒng)頁眉提供方便查閱的tab標(biāo)簽進(jìn)行切換以及對(duì)已經(jīng)緩存頁面進(jìn)行數(shù)據(jù)刷新和清除數(shù)據(jù)操作。具體演示如下圖所示:
在上面演示中實(shí)現(xiàn)了類似 window tab 標(biāo)簽頁效果,會(huì)對(duì)當(dāng)前數(shù)據(jù)進(jìn)行緩存。在瀏覽器中實(shí)現(xiàn)對(duì)路由頁面的緩存可以減少接口請(qǐng)求,也方便了用戶來回切換想搜索的數(shù)據(jù)列表。
原理
Vue 提供的 keep-alive API實(shí)現(xiàn)對(duì)路由組件的緩存。 include 屬性可以綁定一個(gè)數(shù)組,里面是需要路由組件的 name 值,可以實(shí)現(xiàn)對(duì)該路由組件進(jìn)行緩存,如果不需要對(duì)路由進(jìn)行緩存,直接移除該項(xiàng)元素即可。
代碼組織和設(shè)計(jì)
實(shí)現(xiàn)上面的功能,采用 vuex 進(jìn)行全局的緩存數(shù)據(jù)保存,定義為 cacheView ;已經(jīng)打開的路由頁面用 toolBarData 進(jìn)行保存。下圖是代碼是代碼設(shè)計(jì)整體圖:
需要添加一個(gè)路由頁面到 cacheView ,需要有 actions setCacheView 來 commit 一個(gè) change Event 對(duì) state 數(shù)據(jù)進(jìn)行更改,然后修改后的數(shù)據(jù)會(huì)自動(dòng)派發(fā)到 App.vue 中使用到該數(shù)據(jù)的位置(即 keep-alive
處)。而添加標(biāo)簽頁也是類似的流程,不再描述。至于為什么要把標(biāo)簽頁和路由緩存頁面分離成兩個(gè)數(shù)組,主要是有兩方面的考慮:
name
store代碼實(shí)現(xiàn)
store 代碼實(shí)現(xiàn)如下所示,主要需要比較詳細(xì)說明的是 clearToolItem ,這個(gè)函數(shù)是清除標(biāo)簽頁。涉及兩個(gè)規(guī)則:
如果關(guān)閉是當(dāng)前處于激活的標(biāo)簽頁,關(guān)閉之后。處于激活的標(biāo)簽頁就默認(rèn)是最后一個(gè)打開的標(biāo)簽頁。
如果當(dāng)前標(biāo)簽頁是最后一個(gè)(處于激活狀態(tài)),則關(guān)閉后自動(dòng)默認(rèn)它的前一個(gè)為默認(rèn)激活標(biāo)簽頁。
import router from '../router'
export default {
state: {
toolBarData:[],// 保存標(biāo)簽button的數(shù)組
cacheView:[] // 保存需要緩存的數(shù)組
},
getters: {
getToolData(state){
return state.toolBarData;
},
getCacheView(state){
return state.cacheView;
}
},
mutations: {
setToolData(state, data) { // 添加標(biāo)簽按鈕,如果當(dāng)前路由已經(jīng)打開,則不再重復(fù)添加
const inToolbar = state.toolBarData.find(item => item.detail === data.detail)
!inToolbar && state.toolBarData.push({
...data
});
},
setCacheView(state,data){ // 與setToolData類似
if(state.cacheView.includes(data.componentName))
return;
state.cacheView.push(data.componentName);
},
clearToolItem(state,detail){
const index = state.toolBarData.findIndex(item => item.detail === detail);
const isActive = router.app.$route.path == state.toolBarData[index]["detail"];
const len = state.toolBarData.length - 1;
state.toolBarData.splice(index,1);
(index == len || isActive) && router.push({path:state.toolBarData[state.toolBarData.length - 1]["detail"]});
},
clearCacheView(state,viewName){
const index = state.cacheView.findIndex(item => item == viewName);
state.cacheView.splice(index,1);
}
},
actions: {
commitToolBar({commit},data) {
commit("setToolData",data);
commit("setCacheView",data);
},
clearToolBar({commit},data){
commit("clearToolItem",data.detail);
},
clearCache({commit},data){
commit("clearCacheView",data);
}
}
}
入口文件緩存路由
在 App.vue 入口文件,使用 keep-alive 對(duì)匹配的路由組件進(jìn)行緩存,監(jiān)聽當(dāng)前路由變化,添加緩存路由和標(biāo)簽。
<template>
<el-main style="position:relative;margin-top:45px;">
<!--渲染標(biāo)簽的地方-->
<ToolBar></ToolBar>
<div class="routeWrap">
<transition name="fade-transform">
<keep-alive :include="cachedViews">
<router-view></router-view>
</keep-alive>
</transition>
</div>
</el-main>
</template>
<script>
export default {
watch: {
$route() {
// 路由組件名稱(自定義)
const componentName =this.$route.matched[0]["components"]["default"][ "name"];
const detail = this.$route.path;
// 當(dāng)前路由匹配到name
const name = this.$route.meta[0]["name"];
this.$store.dispatch("commitToolBar", { name, detail, componentName });
}
}
}
</script>
ToolBar代碼
這里使用了 elementui 的 el-tag 標(biāo)簽, el-tag 標(biāo)簽帶有動(dòng)畫、關(guān)閉按鈕、主題color等屬性, close 函數(shù)是清除該標(biāo)簽和清除緩存路由(已訪問過)。 click 主要是當(dāng)對(duì)該標(biāo)簽項(xiàng)點(diǎn)擊操作,則切換到該路由頁面。其中 active 是該標(biāo)簽匹配到當(dāng)前路由時(shí)候處于激活狀態(tài)(顏色高亮), el-tag 的動(dòng)畫比較生硬,所以關(guān)閉了。
<template>
<div class="toolbar">
<el-tag
class="toolItem"
type="info"
:disable-transitions="false"
:closable="item.id != 0"
effect="plain"
v-for="(item,index) in getToolData"
:key="index"
:class="{active:$route.path == item.detail}"
@click="redirect(item)"
@close="closeToolItem(item)"
>
<span class="dot" v-if="$route.path == item.detail"></span>
{{item.name}}
</el-tag>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
methods: {
closeToolItem(item, index) {
this.$store.dispatch("clearToolBar", item);
this.$store.dispatch("clearCache", item.componentName);
},
redirect(item) {
this.$router.push({ path: item.detail });
}
},
computed: {
...mapGetters(["getToolData", "getCacheView"])
}
};
</script>
生命周期 activated 和 deactivated
采用了 keep-alive 緩存的路由組件,重新進(jìn)入該路由,路由組件不會(huì)重新創(chuàng)建,所以也就不會(huì)觸發(fā)組件的生命周期函數(shù)(比如說 beforeCreate 、 mounted 等)。所以在對(duì)該頁面進(jìn)行數(shù)據(jù)更新或者清除數(shù)據(jù)。 vue 為我們提供了 activated 和 deactivated 生命周期函數(shù),當(dāng)重新進(jìn)入路由組件會(huì)觸發(fā) activated 函數(shù),離開則會(huì)觸發(fā) deactivated 。
<template>
<div> A page</div>
</template>
<script>
export default {
data(){
return {
form :{
name:'',
password:''
}
}
},
activated(){
this.getList()
},
deactivated(){
Object.keys(this.form).map(key => {
this.form[key] = ''
})
}
}
</script>
總結(jié)
以上所述是小編給大家介紹的vuex + keep-alive實(shí)現(xiàn)tab標(biāo)簽頁面緩存問題,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
Vue3使用Echarts導(dǎo)致tooltip失效問題及解決方法
Vue3 使用 proxy 對(duì)象代理,而 echarts 則使用了大量的全等(===), 對(duì)比失敗從而導(dǎo)致了bug,這篇文章主要介紹了Vue3使用Echarts導(dǎo)致tooltip失效問題及解決方法,需要的朋友可以參考下2023-08-08
vue項(xiàng)目基于WebRTC實(shí)現(xiàn)一對(duì)一音視頻通話
這篇文章主要介紹了vue項(xiàng)目基于WebRTC實(shí)現(xiàn)一對(duì)一音視頻通話效果,實(shí)現(xiàn)代碼分為前端和后端兩部分代碼,需要的朋友可以參考下2024-05-05
vue實(shí)現(xiàn)動(dòng)態(tài)表單動(dòng)態(tài)渲染組件的方式(2)
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)動(dòng)態(tài)表單動(dòng)態(tài)渲染組件的方式第二篇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
vue 組件開發(fā)原理與實(shí)現(xiàn)方法詳解
這篇文章主要介紹了vue 組件開發(fā)原理與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了vue.js組件開發(fā)的原理與實(shí)現(xiàn)方法,需要的朋友可以參考下2019-11-11
使用vue-cli webpack 快速搭建項(xiàng)目的代碼
這篇文章主要介紹了vue-cli webpack 快速搭建項(xiàng)目的教程詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11
VueCli3構(gòu)建TS項(xiàng)目的方法步驟
這篇文章主要介紹了VueCli3構(gòu)建TS項(xiàng)目的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11

