首頁 > 軟體

vue專案keepAlive配合vuex動態設定路由快取方式

2022-04-15 19:00:41

需求

首頁 → 列表頁→ 詳情頁(快取列表頁面 ) → 列表頁(不重新載入列表頁)→ 首頁(清除列表頁的快取)

效果圖

解決方案

直接使用keepAlive會出現一個問題,當從查詢1進入列表頁面,這時快取list元件,然後返回首頁,點選查詢2,會發現list的資料是查詢1的,因為這裡直接呼叫了上一次的快取因此,在返回首頁後需清除list的快取,下次進入list將重新初始化。

利用keepAlive進行路由快取,keepAlive的include 和 exclude 屬性允許元件有條件地快取。

配合vuex維護一個快取陣列即可,不多BB,直接上程式碼

1.App.vue檔案

利用include屬性進行選擇性快取

<template>
  <div style="height: 100%;">
    <keep-alive :include="$store.state.common.cachedRouteNames">
      <router-view />
    </keep-alive>
  </div>
</template>
<script>
export default {
  name: 'App'
};
</script>

2.main.js檔案

設定路由keepAlive狀態

import Vue from 'vue';
// import Vue from 'vue/dist/vue.esm.js'
import App from '../src/App.vue';
import router from '../src/router/index';
// import "../src/assets/style/reset.css";
import 'lib-flexible';
import utils from './utils/utils';
import store from './store/index';
// 設定路由keepAlive狀態
utils.setRouterBeforeEach(router);
// runtime模式
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app');

3.store/modules/common.js檔案

vuex管理快取陣列,編寫新增和刪除快取路由方法

const UPDATE_CACHEDROUTENAMES = 'update_cachedroutenames';
const state = {
  activatedReloadData: true, // 頁面activated時是否需要重新載入
  // 快取的路由列表
  cachedRouteNames: []
};
const mutations = {
  [UPDATE_CACHEDROUTENAMES](st, { action, route }) {
    const methods = {
      add: () => {
        st.cachedRouteNames.push(route);
      },
      delete: () => {
        st.cachedRouteNames.splice(st.cachedRouteNames.findIndex(e => e === route), 1);
      }
    };
    methods[action]();
  }
};
export default {
  namespaced: true,
  state,
  mutations
};

4.utils/utils.js檔案

設定路由keepAlive狀態

import store from '../store/index';
const { cachedRouteNames } = store.state.common;
const changeRoutes = (route, type) => {
  const routeName = route.components.default.name;
  if (routeName && type === 'add' ? !cachedRouteNames.includes(routeName) : cachedRouteNames.includes(routeName)) {
    store.commit('common/update_cachedroutenames', {
      action: type,
      route: routeName
    });
  }
};
// 定義新增快取元件name函數,設定的時元件的name
const addRoutes = (route) => {
  changeRoutes(route, 'add');
};
// 定義刪除快取元件name函數,設定的是元件的name
const deleteRoutes = (route) => {
  changeRoutes(route, 'delete');
};
// 設定路由keepAlive狀態
const setRouterBeforeEach = (router) => {
  router.beforeEach((to, from, next) => {
    // 對該元件是否讀取快取進行處理
    to.matched.forEach((item) => {
      const routes = item.meta.cachedRouteNames;
      if (item.meta.keepAlive && (!routes || (routes && (!from.name || routes.includes(from.name))))) {
        addRoutes(item);
      } else {
        deleteRoutes(item);
      }
    });
    next();
  });
  // 全域性混入。在該元件被解析之後,若是屬於需要快取的元件,先將其新增到快取設定中,進行快取
  Vue.mixin({
    beforeRouteEnter(to, from, next) {
      next(() => {
        to.matched.forEach((item) => {
          if (to.meta.keepAlive) {
            addRoutes(item);
          }
        });
      });
    },
  });
};
export default {
  setRouterBeforeEach
};

5.store/index.js檔案

import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions';
import mutations from './mutations';
import state from './state';
import getters from './getters';
import app from './modules/app';
import common from './modules/common';
Vue.use(Vuex);
const store = new Vuex.Store({
  modules: { app, common },
  state,
  mutations,
  actions,
  getters
});
export default store;

6.router/index.js檔案

  • keepAlive:設定快取
  • cachedRouteNames:設定快取條件
// An highlighted block
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const Home = resolve => require(['../routers/Home.vue'], resolve);
const List = resolve => require(['../routers/list.vue'], resolve);
const Detail = resolve => require(['../routers/detail.vue'], resolve);
const router = new VueRouter({
  routes: [
    {
      name: 'Home',
      path: '/home',
      component: Home
    },
    {
      name: 'List',
      path: '/list',
      component: List,
      meta: {
        keepAlive: true,
        // 快取條件:從List --> Detail 則快取List
        cachedRouteNames: ['Detail']
      }
    },
    {
      name: 'Detail',
      path: '/detail',
      component: Detail
    }
  ]
});
export default router;

7.routers/Home.vue檔案

export default {
  name: 'Home',
  components: {
    HeaderBar
  },
  data() {
    return {
      list: [
        '查詢1',
        '查詢2'
      ]
    };
  },
  created() {
    // this.getData();
    // console.log(111111);
  },
};
</script>

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。 


IT145.com E-mail:sddin#qq.com