vue配合element-ui的tabs动态设置keep-alive动态缓存3级路由页面
二级路由挂载点,由于二级路由页面只有几个基础页面,例如注册登录等,因此全部缓存,如果不缓存的话,会导致切换到二级路由页面后,缓存的三级页面失效。需要注意的是include/exclude绑定的属性是页面中设置的name值 而不是路由中的name值。当在实际项目中 可以运用vuex保存你需要缓存的页面的name值,可以配合tabs使用。当在几个tabs之间来回切换时,不需要更新vuex,直接rout
·
需要注意的是include/exclude绑定的属性是页面中设置的name值 而不是路由中的name值
基础使用方法
<keep-alive include="mytemplate">
<router-view ></router-view>
</keep-alive>
export default {
name:'mytemplate'
data(){
return{}
}
}
当在实际项目中 可以运用vuex保存你需要缓存的页面的name值,可以配合tabs使用
下面是配合element-ui的tabs使用
二级路由挂载点,由于二级路由页面只有几个基础页面,例如注册登录等,不需要缓存,否则会导致退出登陆后登录页面不更新。建议只在三级路由部署页面缓存。
动态缓存的值存在vuex中,默认将home页面缓存
alive_list: ['/home'], // 缓存得页面
在需要用到的页面,取出缓存页面列表
computed: {
cacheviews () {
return this.$store.state.tabs.alive_list
},
key () {
return Date()
}
},
一级路由App.vue
<transition name="el-zoom-in-top" mode="out-in">
<keep-alive :include="cacheviews">
<!-- 一级路由 -->
<router-view ></router-view>
</keep-alive>
</transition>
二级路由
<div class="index-main-content-view-div">
<transition name="el-zoom-in-top" mode="out-in">
<!-- 缓存页面 -->
<keep-alive :include="cacheviews">
<!-- 二级路由 -->
<router-view/>
</keep-alive>
</transition>
</div>
三级路由挂载点
<keep-alive :include="cacheviews">
<!-- 3级路由 -->
<router-view></router-view>
</keep-alive>
先写vuex文件
const tabs = {
state: {
activeName: '/home',
list: [{
'name': '工作台',
'path': '/home'
}],
alive_list: ['/home'], // 缓存得页面
view_key: 1
},
mutations: {
// 切换活动的tag
changeTabsName (state, data) {
state.activeName = data
},
// 清空所有tag
emptyTabs (state) {
state.list = [{
'name': '工作台',
'path': '/home'
}]
state.activeName = '/home'
},
// 添加一个新tage
changeTabs (state, data) {
let list = state.list
let intercept = true
for (let i = 0; i < list.length; i++) {
if (list[i].path === data.path) {
intercept = false
state.activeName = data.path
break
}
}
// 如果此页面不在活动列表中,则添加页面缓存
if (intercept) {
state.list.push(data)
// 添加页面缓存列表
state.alive_list.push(data.path)
state.activeName = data.path
}
},
// 删除一个tag
del_tabs (state, data) { // state:变量,data:新值
let list = state.list // 当前tabs列表
let alive_list = state.alive_list // 当前缓存列表
// 如果匹配上path,将该path从tabs列表里删除
for (let i = 0; i < list.length; i++) {
if (list[i].path === data.path) {
list.splice(i, 1)
}
}
state.list = list // 新的tabs列表
// 如果匹配上path,将该path从alive列表里删除
for (let i = 0; i < alive_list.length; i++) {
if (alive_list[i] === data.path) {
alive_list.splice(i, 1)
}
}
state.alive_list = alive_list // 新的缓存列表
}
}
}
export default tabs
每当点击导航栏时,更新vuex
addTab (item) {
let data = { 'name': item.meta.title, 'path': '/' + item.path }
this.$store.commit('changeTabs', data)
this.$storeLocal.set('tabs', this.$store.state.tabs)
},
当在几个tabs之间来回切换时,不需要更新vuex,直接router跳转就行
当删除tabs时,同样更新vuex
removeTab (targetName) {
// 获取本地缓存中的tab
let tabs = this.$storeLocal.get('tabs')
// let tabs = this.$store.state.list
for (let i = 0; i < tabs.list.length; i++) {
let path = tabs.list[i].path
if (path == targetName) { this.$store.commit('del_tabs', tabs.list[i]) }
}
// 回到工作台
this.$router.push('/')
// 将新的tab列表存入缓存
this.$storeLocal.set('tabs', this.$store.state.tabs)
}
tabs代码:
<template>
<!-- 每点开一个页面会生成一个新的tab -->
<div class="tabs">
<!-- 活动窗口 -->
<el-tabs v-model="$store.state.tabs.activeName" @tab-click="handleClick" @tab-remove="removeTab2" closable>
<el-tab-pane v-for="item in $store.state.tabs.list" :key="item.name" :label="item.name" :name="item.path"></el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
methods: {
// 点击tab
handleClick (tab, event) {
// console.log(this.$store.state.tabs.alive_list)
this.$router.push(tab.name)
},
// 删掉tab,暂不使用
removeTab (targetName) {
// 清空所有vuex中的tab
this.$store.commit('emptyTabs')
// 获取本地缓存中的tab
let tabs = this.$storeLocal.get('tabs')
// 重新生成vuex的列表,不包含删除的tab
for (let i = 0; i < tabs.list.length; i++) {
let path = tabs.list[i].path
if (path !== targetName) { this.$store.commit('changeTabs', tabs.list[i]) }
}
// 回到工作台
this.$router.push('/home')
// 将工作台加入tab
// this.$store.commit('changeTabsName', '/')
// 将新的tab列表存入缓存
this.$storeLocal.set('tabs', this.$store.state.tabs)
},
removeTab2 (targetName) {
console.log('删掉tab:' + targetName)
// 获取本地缓存中的tab
let tabs = this.$storeLocal.get('tabs')
// let tabs = this.$store.state.list
// 遍历storeLocal中存储的tabs列表,如果匹配上,则发起删除方法
for (let i = 0; i < tabs.list.length; i++) {
let path = tabs.list[i].path
if (path == targetName) {
this.$store.commit('del_tabs', tabs.list[i])
}
}
// 将新的tab列表存入缓存
this.$storeLocal.set('tabs', this.$store.state.tabs)
// 跳转至倒数第一个tab
console.log(this.$store.state.tabs.alive_list)
let len = this.$store.state.tabs.alive_list.length
if (len > 0) {
let to_next_page = this.$store.state.tabs.alive_list[len - 1]
this.$store.commit('changeTabsName', to_next_page)
this.$router.push(to_next_page)
} else {
// this.$store.state.tabs.view_key++
this.$store.commit('changeTabsName', '/')
this.$router.push('/home')
this.$store.state.tabs.view_key = 2
}
}
},
created () {
// 从本地缓存取出活动tabs
let tabs = this.$storeLocal.get('tabs') ? this.$storeLocal.get('tabs') : ''
if (tabs === '') {
return false
}
// 仅仅保留最后一个活动tabs
for (let i = 0; i < tabs.list.length; i++) {
let name = tabs.list[i].name
if (name === this.$route.name) {
this.$store.commit('changeTabs', tabs.list[i])
this.$store.commit('changeTabsName', tabs.list[i].path)
this.$storeLocal.set('tabs', this.$store.state.tabs)
break
}
}
}
}
</script>
<style lang="scss">
@import "./tabs.scss";
</style>
由于keep-alive只能缓存二级路由,这里使用递归处理多余的 layout
新建一个js文件
router.js
// 递归处理多余的 layout : <router-view>,让需要访问的组件保持在第一层 layout 层。
// 因为 `keep-alive` 只能缓存二级路由
// 默认初始化时就执行
function keepAliveSplice (to, router) {
if (to.matched && to.matched.length > 2) {
to.matched.map((v, k) => {
if (v.components.default instanceof Function) {
// 区分非懒路由
if (v.components.default.length === 0) {
v.components.default().then((components) => {
if (components.default.name === 'parent') {
to.matched.splice(k, 1)
router.push({ path: to.path, query: to.query })
keepAliveSplice(to)
}
})
}
} else {
if (v.components.default.name === 'parent') {
to.matched.splice(k, 1)
keepAliveSplice(to)
}
}
})
}
}
export {
keepAliveSplice
}
在路由router页面里引用
// 路由守卫
router.beforeEach((to, from, next) => {
keepAliveSplice(to, Router)
next()
})
结果:
更多推荐
已为社区贡献20条内容
所有评论(0)