vue3 控制url更新但不让页面更新
前言
最近遇到一个特定的前端需求
- 要求url每次打开都是正确的详情页面,也就是说每次更换详情页,url必须得更新
- keep-alive 无法使用 keep-alive会让整个页面都缓存,从其它路由跳回来的时候,仍然是之前的状态,不符合业务的要求
- 需要在切换文件的时候,更新url,并且只更新文件展示的那一块儿,其它不更新。
因为有了上面的三点,所以,有了以下方案。
通过history.replaceState控制url变更
history.replaceState
是h5自带的api,能够单纯的改变url,vue-router也是通过这个去改变url的。
onBeforeRouteUpdate
是vue-router 提供的一个hook,能在router.replace
或者router.push 调用后执行。
import { useRouter, useRoute, onBeforeRouteUpdate } from "vue-router";// 阻止路由变更导致的页面刷新 但是当你点回去的时候不会触发
onBeforeRouteUpdate((to, from) => {// 当to和from的path相同时,拦截,不要执行页面的刷新,虽然path相同,但后面的参数不同也符合这个条件,即同一个路由下的页面拦截不刷新页面。if(to.path === from.path) {// console.log('路由更新了,但是没有变化')// 将url变更 但是页面不刷新history.replaceState({}, '', to.fullPath)// 页面不刷新就要手动执行代码,让需要的内容更新....// 一定要返回false 才能阻止vue-router对页面的刷新return false}
})
上面的方案会有一个问题。虽然我们控制了url的改变,但由于返回了false,阻止了页面刷新,也阻止了vue-router本身的更新。
所以 vue-router这个实例对象一直都没变过。这样当你将url切换到其它路径时,没问题,但是想要切换回来,onBeforeRouteUpdate 根本检测不到,因为你的router实例压根就没变化,所以一旦离开最开始进入的页面,想要回来就不行了。
解决无法回到最开始的页面
import { useRouter, useRoute } from "vue-router";
const router = useRouter()
router.replace({path: "/xxx/detail",query: {// 传递对应的参数... updateRouter: Math.random().toString()},
});
通过上面的方法,控制路由跳转,加了一个updateRouter 的随机参数,保证每一次/xxx/detail 这个页面下route实例都发生了变化,每一次onBeforeRouteUpdate都能检测到变化并执行。
其它问题
由于router.replace 或者router.push 在 /xxx/detail 中的所有跳转都被拦截了,并没有改变route实例。
所以在 /xxx/detail 页面 中其它地方,想要获取router.query里面的参数都是拿不到最新的,只能拿到最开始进入页面的那些参数。
所以我们还需要将原本路由中的的参数以新的方式传递和获取,比如放到pinia中或者localstorage中等。