Vue3后退不刷新,前进刷新

核心思想

  1. 使用keep-alive缓存页面信息
  2. 由于vue3中keep-alive只能通过组件名称缓存,每次都会动态创建一个新的组件包装下页面
  3. 每次路由前进时会根据路由的深度分配一个uuid并缓存,然后用此uuid创建一个动态组件包装页面
  4. 此方法可以解决a->b->a->c 然后后退 c->a->b->a的问题

PageKeepAlive组件源码

vue 复制代码
<template>
  <keep-alive :include="include">
    <component v-if="node" :is="node" :key="data.cid" />
  </keep-alive>
</template>
<script setup>
import { uuid } from '@/common/utils/StringUtil'
import { defineComponent, computed, reactive, nextTick } from 'vue'
import {useRouter} from 'vue-router'
const props = defineProps(['data'])

const router = useRouter()

const comp_cache = reactive({})
const position_cache = reactive({})

const include = computed(()=>{
  let target = []
  let expired = new Set(Object.keys(comp_cache))
  for (let cache of Object.values(position_cache)) {
    target.push(cache.cid)
    expired.delete(cache.cid)
  }
  nextTick(()=>{ // 删除过期的缓存
    for (let cid of expired) {
      delete comp_cache[cid]
    }
  })
  return target
})

const node = computed(()=>{
  let data = props.data
  if(!data || !data.cid || !data.comps) return null
  if (!comp_cache[data.cid]) {
    comp_cache[data.cid] = defineComponent({
      name: data.cid,
      setup() {
        return () => data.comps
      }
    })
  }
  return comp_cache[data.cid]
})

router.afterEach((to) => {
  let current = window.history.state.position
  let path = to.path
  for (let i of Object.keys(position_cache)) {
    let cache = position_cache[i]
    if (i > current) { // 大于当前位置的缓存清理掉
      delete position_cache[i]
    }
    if (i == current && cache.path != path) { // replace需要去掉缓存
      delete position_cache[i]
    }
  }
  let cache = position_cache[current]
  if (!cache) {
    position_cache[current] = cache = {
      cid: `comp_${uuid()}`,
      path
    }
  }
  to.meta.cid = cache.cid
})
</script>

使用方式

vue 复制代码
<router-view v-slot="{ Component, route  }">
	<PageKeepAlive :data="{cid: route.meta.cid, comps: Component}" />
</router-view>
相关推荐
ZC跨境爬虫6 小时前
跟着 MDN 学 HTML day_11:(语义化容器全站重构+独立CSS拆分+字体合规引入)
前端·css·ui·重构·html·edge浏览器
ZC跨境爬虫6 小时前
跟着 MDN 学 HTML day_10:(超链接核心语法+路径规则)
前端·css·笔记·ui·html·edge浏览器
GISer_Jing6 小时前
AI原生前端工程化进阶实践:从流式交互架构到端云协同全链路落地
前端·人工智能·后端·学习
被考核重击6 小时前
Vue响应式原理(下)
前端·javascript·vue.js
ZC跨境爬虫15 小时前
跟着 MDN 学 HTML day_9:(信件语义标记)
前端·css·笔记·ui·html
前端老石人15 小时前
HTML 字符引用完全指南
开发语言·前端·html
幼儿园技术家15 小时前
前端如何设计权限系统(RBAC / ABAC)?
前端
前端摸鱼匠17 小时前
Vue 3 的v-bind合并行为:讲解v-bind与普通属性合并的规则
前端·javascript·vue.js·前端框架·ecmascript
REDcker17 小时前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
donecoding19 小时前
一个 sudo 引发的血案:npm 全局包权限错乱彻底修复
前端·node.js·前端工程化