vue頁面快取,可自選是否刪除
阿新 • • 發佈:2022-06-01
需求
後臺管理系統選單之間切換要求實現頁面快取,同個頁面引數不一樣也要快取(比如同個表單詳情頁,id不一樣), 可以來回切換不重新整理裡面資料。
github 地址
https://github.com/wzhGitH/test-menu-cache
首先:
想著使用<keep-alive></keep-alive>來實現,同一路由頁引數不一樣又要快取,所以使用 $route.fullPath 作為key, 根據路由meta裡面的引數來設定是否需要實現快取,
再網上找了很多都是隻能用<keep-alive></keep-alive>實現快取,不能實現動態刪除的, 這樣根本沒法使用。
思路:
所以我就想研究了一下vue 的vnode資料儲存,找找它把keep-alive儲存下來的頁面儲存再哪, 經過大半天的尋找最後終於找到了。
下面貼主要程式碼
選單欄跳轉路由方法
左邊選單欄元件 LeftMenu.vue
// 跳轉 goRouter(item) { if (item.children.length > 0) { item.showSon = !item.showSon; } else { if (item.is_click === "2") {this.$message.warning("近期開放,敬請期待!"); } else { item.menuType = "child"; this.$store.commit('changeBreadcrumb', item); this.$router.push({ path: item.URL_LINK }); } } },
最主要的store,資料
最主要的func
const state = { // 開啟的tab標籤頁物件 cacheList: [], menuList: [], menuActive: {}, isMenuNodeExist: null, isMenuExist: null, fatherMenu: {}, childmenu: {}, isReload: false, reloadRouter: false, menuMap: new Map() }; export default { state, mutations: { // 修改重新整理router initRouter(state){ state.reloadRouter = false; }, // 更新狀態 updateState(state){ state.isReload = !state.isReload; }, // 加入list addCacheMenu (state, item) { state.cacheList.push(item); this.commit('openCacheMenu', item) }, // 快取選單的鍵值對 setMenuMap(state, menuMap){ state.menuMap = menuMap; }, // open Menu openCacheMenu (state, item) { state.menuActive = item; }, // 刪除menu delMenu(state, index){ state.cacheList.splice(index, 1); }, deleteMenu(state, _this){ let url = _this.$route.fullPath; let index = state.cacheList.findIndex((item)=>{ return item.fullPath === url; }); state.reloadRouter = false; if(index !== -1){ state.cacheList.splice(index, 1); _this._deleteType = "view"; this.commit('dropCache', _this) } }, // 判斷Menu是否存在 isMenuExist(state, url){ let isExist = state.cacheList.some((item)=>{ return item.fullPath === url; }); state.isMenuExist = isExist; }, isMenuListExist(state, nodeId){ let isExist = state.menuList.some((item)=>{ return item.NODE_ID === nodeId; }); state.isMenuNodeExist = isExist; }, // 變更麵包屑 changeBreadcrumb(state,item){ if(item.menuType === "child") { state.childmenu = item; sessionStorage.setItem("childmenu", JSON.stringify(item)); } if(item.menuType === "father"){ state.fatherMenu = item; state.childmenu = {}; sessionStorage.setItem("menu", JSON.stringify(item)); sessionStorage.removeItem("childmenu"); } this.commit('isMenuListExist', item.NODE_ID); if (!state.isMenuNodeExist) { state.menuList.push(item); } }, // 變更路由 checkRouterLink(state, item){ let url = item.fullPath; this.commit('isMenuExist', url); if (!state.isMenuExist) { // 該標籤當前沒有開啟 this.commit('addCacheMenu', item) } else { // 該標籤是已經開啟過的,需要啟用此標籤頁 this.commit('openCacheMenu', item) } }, // 刪除快取 dropCache(state, _this){ state.reloadRouter = _this.reloadRouter ? _this.reloadRouter : false; let children = ""; // 頁面內的返回或關閉按鈕 if(_this._deleteType === "view"){ children = _this; // 上面cahcheMenu 的關閉 } else { let cacheList = state.cacheList; let comIndex = cacheList.length - _this.index; children = _this.$parent.$children[_this.$parent.$children.length - comIndex - 1]; } console.log(children.$vnode); let key = children.$vnode.key; let cache = children.$vnode.parent.componentInstance.cache; let keys = children.$vnode.parent.componentInstance.keys; if (cache[key]){ if (keys.length) { var index = keys.indexOf(key); if (index > -1) { keys.splice(index, 1); } } delete cache[key]; } children.$destroy(); }, // 初始化所有快取 clearAllValue(state, item){ state.cacheList = []; state.menuList = []; state.menuActive = {}; state.isMenuNodeExist = null; state.isMenuExist = null; state.reloadRouter = false; state.fatherMenu = {}; state.childmenu = {}; sessionStorage.removeItem("menu"); sessionStorage.removeItem("childmenu"); } }, };
路由配置
AppPage.vue 根據 keepAlive 來判斷是否快取
<keep-alive> <router-view v-if="$route.meta.keepAlive" :key="$route.fullPath"></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive" :key="$route.fullPath"></router-view>
刪除快取快照
後面又要求, 比如新增了某條資料後返回列表,要重新請求一下列表資料(不重新整理頁面)
改版後 加個引數 true 就是要 重新獲取資料(不重新整理頁面)
更改頁
列表頁, 監聽資料去執行方法
程式碼已經存放到github 上, 下載下來就可以執行。