1. 程式人生 > 其它 >vue頁面快取,可自選是否刪除

vue頁面快取,可自選是否刪除

需求

  後臺管理系統選單之間切換要求實現頁面快取,同個頁面引數不一樣也要快取(比如同個表單詳情頁,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 上, 下載下來就可以執行。