vue keepAlive组件大家都不陌生,用于对组件进行缓存(离开路由不会销毁组件),它有以下props

Props:

  1. include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  2. exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  3. max - 数字。最多可以缓存多少组件实例。

可以利用上面prop对组件进行缓存或不缓存、但在实际开发过程中可能会遇到以下需求

需求:

  1. A界面=>B界面 (期望B界面是新生成的)
  2. B界面=>C界面 (对B界面进行缓存)
  3. C界面回退=>B界面(恢复缓存)

问题分析

  1. 如果对B界面设置keepalive缓存,则A界面=>B界面会读之前的缓存,不满足需求1。
  2. 如果B界面不设置缓存,在C界面回退=>B界面会重新生成界面,不满足需求3。

解决方法(动态缓存)

使用动态缓存则需要在组件和路由配置中设置name属性(两者需保持一致),因为vue会根据name属性作为是否缓存依据

  1. 使用keep-aliveinclude属性对组件进行缓存。
  2. 使用vuex管理需要缓存的组件name属性数组。
//根组件
<keep-alive :include="cachedViews" :max="15">
   <router-view :key="key" />
</keep-alive>
// script
computed: {
    cachedViews () {
      return this.$store.state.cachedViews.cachedViews
    },
    key () {
      return this.$route.path
    },
 },
 // 监听路由变化,为keepAlive:true 的路由自动添加到缓存数组
 watch: {
    $route: {
      immediate: true,
      handler (route) {
        const { name, meta: { keepAlive } } = route
        if (name && keepAlive) {
          this.$store.commit('cachedViews/ADD_CACHED_VIEW', route)
        }
      },
    },
  },

3.新建一个vuex模块cachedViews.js,cachedViews数组包含缓存的组件name属性。

const state = {
  cachedViews: [], // 示例 ['TemplateB', 'TemplateC']
}

const mutations = {
 // 添加缓存
  ADD_CACHED_VIEW: (state, view) => {
    if (state.cachedViews.includes(view.name)) {
      return
    }
    state.cachedViews.push(view.name)
  },
// 移除缓存
  DEL_CACHED_VIEW: (state, view) => {
    const index = state.cachedViews.indexOf(view.name)
    index > -1 && state.cachedViews.splice(index, 1)
  },

}

export default {
//开启命名模块
  namespaced: true,
  state,
  mutations,
}

  1. Store中引入。
import Vue from 'vue'
import Vuex from 'vuex'
import cachedViews from './cachedViews'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  }, 
  modules: {
    cachedViews,
  },
})

  1. B界面设置缓存( keepAlive: true)。
{
   name: 'order', // 此处name必须与组件内的name属性一致 export default { name:'order'}
   path: '/order',
   component: () => import('../views/me/order/index'),
   meta: { title: '我的订单', keepAlive: true },
 },
  1. B界面使用beforeRouteLeave组件路由守卫,解决从A界面=>B界面(需求1)有缓存的问题。
 // 官方路由介绍
 beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
  1. 在离开当前路由时调用DEL_CACHED_VIEW方法从缓存列表中移除。

  beforeRouteLeave (to, from, next) {
  // 去这些界面我需要缓存
    const routerArr = ['/TemplateC', '/TemplateD']
    if (!routerArr.includes(to.path)) {
    // 不在缓存列表中,从cachedViews缓存列表中移除
      this.$store.commit('cachedViews/DEL_CACHED_VIEW', form)
    }
    next()
  },

至此我们就解决了动态缓存的问题啦!

总结

  1. 利用include可以实现对组件是否缓存。
  2. 利用vuex对缓存组件的name属性进行动态管理。
  3. beforeRouteLeave组件路由守卫,动态移除缓存。
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐