vue3同时打开多个相同路由页面,按id不同区分缓存

一、配置路由

// params方式传递参数 
 { path: '/show/:id',  component: () => import('@/views/page/Show.vue'), 
    meta: { name: 'show' , keepAlive: true } 
  },

二、配置路由缓存

// !!! 重点 -- 以完整带参数的路由地址作为缓存key
// :key="route.fullPath"
// cachedComponents Strin<Array> 是存储的组件name
<router-view v-slot="{ Component }">
  <keep-alive :include="cachedComponents">
    <component :is="Component" :key="route.fullPath" />
  </keep-alive>
</router-view>

三、使用路由卫士监听路由跳转

 import { useSideStore } from '@/stores/side'
// addMenuList 调用pinia中封装的function 作用是往cachedComponents添加组件name
router.beforeEach((to, from, next) => {
  const sideStore = useSideStore()
  sideStore.addMenuList(to)
  next()
})
pinia 处理缓存的side.js
import { defineStore } from 'pinia'

export const useSideStore = defineStore({
  id: 'side',
  state: () => {
    return {
      cachedComponents: [], // 菜单列表
      openPaths: [], // 打开的页面信息
    }
  },
  getters: {},
  actions: {
    // 添加菜单列表
    addMenuList(item) {
      const {meta, fullPath} = item
      if(!this.cachedComponents.includes(meta.name) && meta.keepAlive){
        this.cachedComponents.push(meta.name)
      }
      if(!this.openPaths.some(i => i.fullPath === fullPath)){
        this.openPaths.push(item)
      }
    },
    // 移除菜单列表
    removeMenuList(item) {
      const {fullPath, meta} = item
      if(this.cachedComponents.includes(meta.name)){
        this.cachedComponents = this.cachedComponents.filter(i => i !== meta.name)
      }
      if(this.openPaths.some(i => i.fullPath === fullPath)){
        this.openPaths = this.openPaths.filter(i => i.fullPath !== fullPath)
      }
    }
  },
  // 开启数据缓存
  persist: {
    enabled: true,
    strategies: [{
      key: 'vite_admin_side',
      storage: sessionStorage,
    }]
  }
})

四、使用

//  缓存测试
<el-button type="primary" @click="router.push('/show/1')">show/1</el-button>
<el-button type="primary" @click="router.push('/show/2')">show/2</el-button>

// 样式就是自己写吧
<div class="scroll-box">
  <div class="tab" :class="{ 'tab-active': v.fullPath === route.fullPath}" v-for="v in openPaths" @click="handleClickTab(v)">
     <span>{{ v.meta.name }}</span>
     <el-icon  @click="handleCloseTab(v)"><Close /></el-icon>
  </div>
</div>
<router-view v-slot="{ Component }">
  <keep-alive :include="cachedComponents">
     <component :is="Component" :key="route.fullPath" />
  </keep-alive>
</router-view>
import { ref } from 'vue'
import { storeToRefs } from "pinia"
import { useRouter} from 'vue-router'
import { useSideStore } from '@/stores/side'
import { Close } from '@element-plus/icons-vue'

const sideStore = useSideStore()
const { cachedComponents, openPaths } = storeToRefs(sideStore)
const router = useRouter()
const sideOpen = ref(false)
const menu = ref([])
const isScroll = ref(false)
const handleClick = () => {
  sideOpen.value = !sideOpen.value
}
const handleClickMenu = (row) => {
  router.push(`/show/${row.id}`)
}
const handleClickTab = (row) => {
  router.push(row)
}
const handleCloseTab = (row) => {
  sideStore.removeMenuList(row)
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容