vuex + keep-alive實現(xiàn)tab標簽頁面緩存功能
在開發(fā)很多管理系統(tǒng)過程之中,常遇到這種需求,需要對打開路由頁面進行緩存,然后在系統(tǒng)頁眉提供方便查閱的tab標簽進行切換以及對已經(jīng)緩存頁面進行數(shù)據(jù)刷新和清除數(shù)據(jù)操作。具體演示如下圖所示:
在上面演示中實現(xiàn)了類似 window tab 標簽頁效果,會對當前數(shù)據(jù)進行緩存。在瀏覽器中實現(xiàn)對路由頁面的緩存可以減少接口請求,也方便了用戶來回切換想搜索的數(shù)據(jù)列表。
原理
Vue 提供的 keep-alive API實現(xiàn)對路由組件的緩存。 include 屬性可以綁定一個數(shù)組,里面是需要路由組件的 name 值,可以實現(xiàn)對該路由組件進行緩存,如果不需要對路由進行緩存,直接移除該項元素即可。
代碼組織和設(shè)計
實現(xiàn)上面的功能,采用 vuex 進行全局的緩存數(shù)據(jù)保存,定義為 cacheView ;已經(jīng)打開的路由頁面用 toolBarData 進行保存。下圖是代碼是代碼設(shè)計整體圖:
需要添加一個路由頁面到 cacheView ,需要有 actions setCacheView 來 commit 一個 change Event 對 state 數(shù)據(jù)進行更改,然后修改后的數(shù)據(jù)會自動派發(fā)到 App.vue 中使用到該數(shù)據(jù)的位置(即 keep-alive
處)。而添加標簽頁也是類似的流程,不再描述。至于為什么要把標簽頁和路由緩存頁面分離成兩個數(shù)組,主要是有兩方面的考慮:
name
store代碼實現(xiàn)
store 代碼實現(xiàn)如下所示,主要需要比較詳細說明的是 clearToolItem ,這個函數(shù)是清除標簽頁。涉及兩個規(guī)則:
如果關(guān)閉是當前處于激活的標簽頁,關(guān)閉之后。處于激活的標簽頁就默認是最后一個打開的標簽頁。
如果當前標簽頁是最后一個(處于激活狀態(tài)),則關(guān)閉后自動默認它的前一個為默認激活標簽頁。
import router from '../router' export default { state: { toolBarData:[],// 保存標簽button的數(shù)組 cacheView:[] // 保存需要緩存的數(shù)組 }, getters: { getToolData(state){ return state.toolBarData; }, getCacheView(state){ return state.cacheView; } }, mutations: { setToolData(state, data) { // 添加標簽按鈕,如果當前路由已經(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 對匹配的路由組件進行緩存,監(jiān)聽當前路由變化,添加緩存路由和標簽。
<template> <el-main style="position:relative;margin-top:45px;"> <!--渲染標簽的地方--> <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; // 當前路由匹配到name const name = this.$route.meta[0]["name"]; this.$store.dispatch("commitToolBar", { name, detail, componentName }); } } } </script>
ToolBar代碼
這里使用了 elementui 的 el-tag 標簽, el-tag 標簽帶有動畫、關(guān)閉按鈕、主題color等屬性, close 函數(shù)是清除該標簽和清除緩存路由(已訪問過)。 click 主要是當對該標簽項點擊操作,則切換到該路由頁面。其中 active 是該標簽匹配到當前路由時候處于激活狀態(tài)(顏色高亮), el-tag 的動畫比較生硬,所以關(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 緩存的路由組件,重新進入該路由,路由組件不會重新創(chuàng)建,所以也就不會觸發(fā)組件的生命周期函數(shù)(比如說 beforeCreate 、 mounted 等)。所以在對該頁面進行數(shù)據(jù)更新或者清除數(shù)據(jù)。 vue 為我們提供了 activated 和 deactivated 生命周期函數(shù),當重新進入路由組件會觸發(fā) activated 函數(shù),離開則會觸發(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實現(xiàn)tab標簽頁面緩存問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Vue3使用Echarts導(dǎo)致tooltip失效問題及解決方法
Vue3 使用 proxy 對象代理,而 echarts 則使用了大量的全等(===), 對比失敗從而導(dǎo)致了bug,這篇文章主要介紹了Vue3使用Echarts導(dǎo)致tooltip失效問題及解決方法,需要的朋友可以參考下2023-08-08vue實現(xiàn)動態(tài)表單動態(tài)渲染組件的方式(2)
這篇文章主要為大家詳細介紹了vue實現(xiàn)動態(tài)表單動態(tài)渲染組件的方式第二篇,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04