路由页面缓存与不缓存共存方案

154 阅读1分钟

一、背景

  1. 页面切换不缓存路由页面组件状态
  2. 当前页面返回上一个路由页面,需要看到上一个路由页面的操作状态,不是页面初始化加载状态

二、技术方案

  1. 使用keep-alive和prop字段include实现,只需维护include的绑定值,就是下面的keepAliveNames【重要提示:绑定的值是命名路由的name,且路由组件的文件名也需要保持一致】
  2. 字段设计
  • keepAliveNames:需要缓存的路由组件name,ts类型string[]
  • keepAliveRouteNameMap:缓存路由与下一个路由组件name绑定关系,ts类型Map<string, string>
  • viewLastPageSnapshot 需要查看上一个路由组件缓存的快照
  1. api方法设计
// 路由手动跳转时调用
addKeepAliveName(routeName?: IRouteName, nextRouteName?: IRouteName) {
  if (routeName && nextRouteName) {
    // 缓存命名路由
    this.keepAliveNames.push(routeName)

    // 绑定当前命名路由与下一个需要跳转的命名路由的映射关系
    this.keepAliveRouteNameMap.set(routeName, nextRouteName)
  }
},
// 全局守卫before钩子
updateKeepAliveNameBeforeRouteEach(routeName?: IRouteName) {
  if (
    routeName &&
    this.keepAliveNames.length > 0 &&
    this.keepAliveNames[0] === routeName &&
    !this.viewLastPageSnapshot
  ) {
    this.clearKeepAliveName()
  }
},
// 全局守卫after钩子
updateKeepAliveNameAfterRouteEach(routeName?: IRouteName, lastRouteName?: IRouteName) {
  if (routeName && lastRouteName) {
    // 上一个路由被缓存,且绑定了当前路由页面,不需要做啥
    if (
      this.keepAliveRouteNameMap.get(lastRouteName) === routeName &&
      this.keepAliveNames[0] === lastRouteName
    ) {
      // nothing todo
    }
    // 被缓存的路由 被上一个页面返回,需要解绑映射关系,并移除缓存命名路由
    else if (
      this.keepAliveRouteNameMap.get(routeName) === lastRouteName &&
      this.keepAliveNames[0] === routeName
    ) {
      this.keepAliveRouteNameMap.clear()
      nextTick(() => (this.keepAliveNames = []))
    } else {
      this.clearKeepAliveName()
    }
  }
  this.viewLastPageSnapshot = false
},
clearKeepAliveName() {
  this.keepAliveRouteNameMap.clear()
  this.keepAliveNames = []
}

三、示例

  1. A页面,点击 抽屉弹窗上的 点击查看b页面详情 按钮
const routeStore = useRouteStore()

const onViewClick = () => {
  routeStore.addKeepAliveName(router.currentRoute.value.name, 'FormilyPreset')
  router.push({ name: 'FormilyPreset' })
}
  1. B页面,点击返回上一页
const routeStore = useRouteStore()

const onBack = () => {
  routeStore.viewLastPageSnapshot = true
  history.back()
}