背景
在日常的业务开发中,遇到了个问题,从一个列表页进入到子页面,当再次返回列表页的时候,用户心愿保留之前的搜寻信息,比方选中了分页为第4页或输出的搜寻条件(id)之类的。
列表页 -> 子页面
子页面 -> 列表页(此时保留上次的信息)
思路
利用长久化数据状态,保留之前的记录信息
这是我第一种想到的办法,利用vuex,cookie,locaStorage,indexdb,用什么样的存储形式,目标只是为了将咱们之前的操作记录保留下来,比方我输出的搜寻信息,我点击列表的分页信息。
流程如下
1️ 首先定义一个配置项,该配置项如下:
const RouterCached = new Map([ ['ListName', ['OneChildName', 'TwoChildName']]]);
2️ 在List组件的beforeRouteLeave钩子中缓存数据
3️ 在List组件的beforeRouteEnter钩子中读取缓存数据,执行还原操作。这里有个前提是,from的钩子必须是RouterCached对应的路由名称,也就是如果不在配置的表中,咱们革除缓存,不做任何还原操作。
利用keep-alive组件
vue中keep-alive介绍
keey-alive新增了几个重要的属性
借助社区上的解决方案
得出了如下思路
1. 搭配vue-router,实现组件的缓存
app.vue文件中利用include属性配合router-view,这里的目标就是对cachedViews中的组件进行keepAlive
cachedViews在这里是组件的name汇合
<template> <div class="app-main"> <div class="app-container" id="app-container"> <keep-alive :include="cachedViews"> <router-view :key="key" /> </keep-alive> </div> </div></template><script lang="ts">import Vue from 'vue';export default Vue.extend({ name: 'AppMain', computed: { cachedViews() { return this.$store.state.cachedViews; }, key() { return this.$route.path; }, },});</script>
2. 封装对cacheView的操作
接下来咱们在store在对cacheView包装几个操作
- 增加须要缓存的components
- 革除指定已被缓存的components
- 革除所有被缓存的components
import { Route } from 'vue-router';export interface RouteView extends Partial<Route> { title?: string}const state = { cachedViews: []};const mutations = { ADD_CACHED_VIEW: (status, route: RouteView) => { if (status.cachedViews.includes(route.name)) return; if (route.meta && route.meta.cache) { status.cachedViews.push(route.name); } }, DEL_ALL_CACHED_VIEWS: (status) => { status.cachedViews = []; }, DEL_CACHED_VIEW: (status, route: RouteView) => { const index = status.cachedViews.indexOf(route.name); if (index > -1) { status.cachedViews.splice(index, 1); } },};const actions = { addCachedView({ commit }, route: RouteView) { commit('ADD_CACHED_VIEW', route); }, delAllCachedViews({ commit }) { commit('DEL_ALL_CACHED_VIEWS'); }, delCachedView({ commit }, route: RouteView) { commit('DEL_CACHED_VIEW', route); },};export default { state, mutations, actions};
3. 全局钩子拦挡缓存
接下来在全局的路由钩子router.beforeEach
中退出该办法的逻辑
const handlerCached = (to: RouteView, from: RouteView) => { const { cachedViews } = store.state; // 革除除列表到详情外的缓存, 列表与详情需isback为对方name if (!(to.meta.isback && to.meta.isback.includes(from.name))) { store.dispatch('appMain/delAllCachedViews'); } // 后退时,一一革除缓存链 cachedViews.forEach((name: string, index: number) => { if (name === from.name && cachedViews[index - 1] && cachedViews[index - 1] === to.name) { store.dispatch('appMain/delCachedView', from); } }); const { name } = to; if (name) { store.dispatch('appMain/addCachedView', to); }};
4. 路由配置
最初一步,就是须要在路由配置中meta字段,增加isback, cache字段,这两个字段和办法的思路是统一的。
cache示意须要缓存的组件(List),
isback示意从那个组件回到须要缓存的组件(Child)
如下的配置:
[ { path: 'list', component: LayoutEmpty, meta: { title: '设施管控', hiddenPage: true, }, redirect: '/device/list/deviceLists', children: [ { path: 'deviceLists', code: 'deviceLists', name: 'DeviceLists', component: DeviceLists, meta: { title: 'ListName', cache: true, }, hidden: true, }, { path: 'detail', code: 'deviceDetail', name: 'DeviceDetial', component: DeviceDetail, hidden: true, meta: { title: 'OneChildName', onHidden: true, isback: 'DeviceLists' }, }, { path: 'log', code: 'log', name: 'Log', component: Log, hidden: true, meta: { title: 'TwoChildName', onHidden: true, isback: 'DeviceLists' }, }, ], },]
⚠️注意事项
最初,须要留神一点isback对应的名字是须要缓存的名字,在routerConfig中为name,组件中的name也须要保持一致。