vue3.0 前进刷新后退缓存

app.vue 入口



利用 vuex 保存缓存记录,如在 store 目录新建 index.js

import { createStore } from 'vuex'
import _ from 'lodash'
const state = {
  historyVirtualRoutes: [], // 虚拟路由栈
  include: [], // 缓存集合
  exclude: [], // 不缓存集合,确保及时清除缓存
}
const getters = {
  historyVirtualRoutes: state => state.historyVirtualRoutes,
  include: state => state.include,
  exclude: state => state.exclude
}
const actions = {
  // 处理缓存问题
  handleInclude({ commit, dispatch, getters }, { to, from }) {
    if (to.params.__routerType === 'push' || to.query.__routerType === 'push') {
      // push 方法跳转
      commit('PUSH_INCLUDE', to.name)
      commit('PUSH_HISTORY_VIRTUAL_ROUTES', to)
    } else if (to.params.__routerType === 'replace' || to.query.__routerType === 'replace') {
      // replace 方法跳转
      commit('POP_INCLUDE', from.name)
      commit('PUSH_INCLUDE', to.name)
      commit('POP_HISTORY_VIRTUAL_ROUTES', from)
      commit('PUSH_HISTORY_VIRTUAL_ROUTES', to)
    } else {
      let len = getters.historyVirtualRoutes.length
      let flag = len && getters.historyVirtualRoutes[len - 1]['path'] === from.path
      if (flag) { // 返回
        commit('POP_INCLUDE', from.name)
        commit('POP_HISTORY_VIRTUAL_ROUTES')
      } else { // 非返回
        commit('PUSH_INCLUDE', to.name)
        commit('PUSH_HISTORY_VIRTUAL_ROUTES', to)
      }
    }
    // 处理 meta.keepAlive 参数缓存
    dispatch('handleIncludeKeepAlive', to)
    dispatch('handleIncludeKeepAlive', from)
  },
  // 处理路由 meta.keepAlive 参数方法
  handleIncludeKeepAlive({ commit }, params) {
    if (params.meta.hasOwnProperty('keepAlive')) {
      if (params.meta.keepAlive === true || params.meta.keepAlive === 'true')
        commit('PUSH_INCLUDE', params.name)
      else if (params.meta.keepAlive === false || params.meta.keepAlive === 'false')
        commit('POP_INCLUDE', params.name)
    }
  },
  // 重置缓存
  clearInclude({ commit }) {
    commit('CLEAR_INCLUDE')
  }
}
const mutations = {
  // 虚拟路由栈入栈
  'PUSH_HISTORY_VIRTUAL_ROUTES'(state, value) {
    state.historyVirtualRoutes.push(value)
  },
  // 虚拟路由栈出栈
  'POP_HISTORY_VIRTUAL_ROUTES'(state, value) {
    if (_.isPlainObject(value)) {
      let i = _.findLastIndex(state.historyVirtualRoutes, item => item.path === value.path)
      if (i !== -1) { // 删除传入的指定路由
        state.historyVirtualRoutes.splice(i, 1)
        return
      }
    }
    state.historyVirtualRoutes.pop() // 不传默认删除最后一个路由
  },
  // include 缓存集合入栈,同时需要 exclude 不缓存集合出栈
  'PUSH_INCLUDE'(state, value) {
    if (!value) return
    let i = state.include.indexOf(value)
    if (i === -1 && value)
      state.include.push(value)
    let index = state.exclude.indexOf(value)
    if (index !== -1) {
      _.remove(state.exclude, item => item === value)
    }
  },
  // include 缓存集合出栈,同时需要 exclude 不缓存集合入栈
  'POP_INCLUDE'(state, value) {
    let i = state.include.indexOf(value)
    if (i !== -1)
      _.remove(state.include, item => item === value)
    let index = state.exclude.indexOf(value)
    if (index === -1 && value)
      state.exclude.push(value)
  },
  // 重置缓存集合
  'CLEAR_INCLUDE'(state) {
    state.include = []
  }
}
export default createStore({
  state,
  getters,
  actions,
  mutations
})

新建一个 js 文件重写 router.push router.replace 方法,如在 utils 目录新建 use-router.js

注意:vue-router4.1.4及以上版本params参数会失效,此时需要将params传参修改为query传参

import { useRouter } from 'vue-router'
// 重写 push replace 方法
export const _useRouter = function () {
  const router = useRouter()
  console.log(router);
  // 重写 push
  const _push = router.push
  router.push = function push(to) {
    if (_.isString(to))
      to = { path: to, query: { __routerType: 'push' } }
    else {
      to.params = to.params || {}
      if (!to.params.hasOwnProperty('__routerType'))
        to.params.__routerType = 'push'
    }
    return _push.call(this, to)
  }
  // 重写 replace 
  const _replace = router.replace
  router.replace = function replace(to) {
    if (_.isString(to))
      to = { path: to, query: { __routerType: 'replace' } }
    else {
      to.params = to.params || {}
      if (!to.params.hasOwnProperty('__routerType'))
        to.params.__routerType = 'replace'
    }
    return _replace.call(this, to)
  }
  return router
}

router 目录新建 index.js ,对路由 afterEach 阶段进行拦截

import store from '@/store/index'
import { createRouter, createWebHistory } from 'vue-router'
import _ from 'lodash'
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes: [
    // {
    //   path: '/test',
    //   name: 'Test',
    //   component: () => import('../views/Test.vue')
    // },
  ]
})
// 路由 afterEach 拦截,用于处理页面缓存
router.afterEach((to, from) => {
  if (to.params.hasOwnProperty('keepAliveTo'))
    to.meta.keepAlive = to.params.keepAliveTo
  else if (to.query.hasOwnProperty('keepAliveTo'))
    to.meta.keepAlive = to.query.keepAliveTo
  if (to.params.hasOwnProperty('keepAliveFrom'))
    from.meta.keepAlive = to.params.keepAliveFrom
  else if (to.query.hasOwnProperty('keepAliveFrom'))
    from.meta.keepAlive = to.query.keepAliveFrom
  // 处理路由传参方法
  const changeRoutes = routeObj => {
    return {
      fullPath: routeObj.fullPath,
      hash: routeObj.hash,
      name: routeObj.name,
      path: routeObj.path,
      meta: { ...routeObj.meta },
      params: { ...routeObj.params },
      query: { ...routeObj.query }
    }
  }
  let params = {
    to: changeRoutes(to),
    from: changeRoutes(from)
  }
  store.dispatch('handleInclude', params)
})
export default router

main.js 注册,如:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App)
app.use(store) // 挂载 vuex
app.use(router) // 挂载路由
app.mount('#app')

至此已完成,下面简单说明路由使用方法:

  • 页面必须添加 name 属性,如:
import { defineComponent } from "vue";
export default defineComponent({
  name: "PageA"
});
  • 现在路由默认前进刷新后退缓存,正常使用路由跳转方法即可,如:
import { defineComponent } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
  name: "PageA",
  setup() {
    const router = useRouter();
    // 跳转到 PageTest 页面
    const toPageTest  = () => {
      router.push({ name: "PageTest " });
    };
    return {
      toPageTest  
    };
  }
});
  • 路由跳转时可通过传参 keepAliveTokeepAliveFrom 参数(paramsquery 参数均可)动态实现页面是否缓存
// 例子1:A页面 ==> B页面,A页面跳转到B页面,实现从B页面返回时,A页面也刷新(即不缓存A页面)
// 在A页面跳到B页面时传参 keepAliveFrom
import { defineComponent } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
  name: "PageA",
  setup() {
    const router = useRouter();
    // 跳转到 PageB 页面
    const toPageB = () => {
      router.push({
        name: "PageB",
        params: { keepAliveFrom: false }
      });
    };
    return {
      toPageB
    };
  }
});

// 例子2:A页面 ==> B页面,A页面跳转到B页面,从B页面返回A页面或其他页面,再次进入B页面实现B页面缓存(即缓存B页面)
// 在A页面跳到B页面时传参 keepAliveTo
import { defineComponent } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
  name: "PageA",
  setup() {
    const router = useRouter();
    // 跳转到 PageB 页面
    const toPageB = () => {
      router.push({
        name: "PageB",
        params: { keepAliveTo: true }
      });
    };
    return {
      toPageB
    };
  }
});
  • 通过配置路由时配置 meta.keepAlive 的值控制页面是否缓存。(提示:这种方法不够灵活,如有页面特殊缓存需要推荐使用上面的方法,上面方法本质上也是通过 keepAliveFrom keepAliveTo 动态设置页面路由 meta.keepALive 的值的)
// 例子1:A页面 ==> B页面,A页面跳转到B页面,实现从B页面返回时,A页面也刷新(即不缓存A页面)
// 配置 PageA 路由时,设置 `meta.keepAlive` 为 `false` 即可,如:
{
  path: "/page-a",
  name: "PageA",
  component: () => import("@/views/page-a"),
  meta: {
    keepAlive: false
  }
}

// 例子2:A页面 ==> B页面,A页面跳转到B页面,从B页面返回A页面或其他页面,再次进入B页面实现B页面缓存(即缓存B页面)
// 配置 PageB路由时,设置 `meta.keepAlive` 为 `true` 即可,如:
{
  path: "/page-b",
  name: "PageB",
  component: () => import("@/views/page-b"),
  meta: {
    keepAlive: true
  }
}

你可能感兴趣的:(vue,javascript)