前端 Vue路由返回恢复页面状态的实现方案
共 2864字,需浏览 6分钟
·
2021-07-19 03:43
来源 | https://www.cnblogs.com/skuld-yi/archive/2021/07/13/15004664.html
需求描述
方案一:将搜索参数存储在路由参数(route.query)中,加载页面时根据参数搜索 优点:刷新不影响;实现简单 缺点:参数只能是基础类型、长度受限;路径看起来比较难看;只对浏览器返回有效,手动跳转回首页不行 方案二:使用路由守卫钩子,在离开页面前本地存储页面参数(vuex、Local Storage 等等) 优点:参数类型长度都比较自由;路径看起来清爽美观;对任意方式返回主页都有效 缺点:需要额外进行数据存储操作,如果使用store模式或vuex则刷新页面失效
方案一:路由参数
// 搜索页面
search(param) {
// 其他处理
this.$router.push({
name: "Index",
query: { ...this.queryParam }, // 将对象展开为键值
});
},
这里要注意 query 传参和 params 传参的区别:前者的参数会以 ?k1=v1&k2=v2 的形式续在路径后面,能直接在地址栏中看到,因此不受页面跳转、刷新影响;后者只在第一次跳转到对应页面时起作用,再刷新跳转就没有了。
因此这里要使用 query 传参。如果把参数按照格式手动写在 path 中也是可以的,但易读性和扩展性明显更差,除非只有一两个简单参数,否则不推荐。
另外,由于这个参数是要放进路径里的,因此只能是基本类型的键值对,数组或对象不能很好地支持。
如果参数简单,可以将相应的对象展开当做参数(需要保证不同对象中没有重名键),但在跳转到的搜索结果页面中读取时,就只能逐个属性的获取。
// 搜索结果页面
mounted() {
// 区分 $route 和 $router
if (this.$route.query.type) {
let type = this.$route.query.type;
let keyword = this.$route.query.keyword;
// ...逐一获取各个参数
// 进行搜索操作
} else {
// 没有搜索参数(因为我这搜索结果和主页是同一个页面,所以有可能只是正常打开主页)
}
},
方案二:本地存储参数
由于我这想存的参数是三个对象,展开成键值取着又太不方便,所以使用了这种方案。
由于项目里本来也使用了 vuex,就顺便存在了 vuex 里面,根据实际情况存在哪儿都行。
vuex 的缺点是一刷新就刷没了,对于搜索结果这种优化体验性质的功能影响不大;如果有对应需求可以存在 local storage 里面。
因为我的需求中有很多中方式改变参数,在改变时存储参数太麻烦,而且容易出错或遗漏。因此这里选择在路由跳转之前再统一存储所需参数。
Vue Router 提供了路由导航守卫系列 API 来实现相应功能,具体包括全局的前置/解析/后置守卫、路由配置守卫、组件守卫等方式。
所谓”守卫“,其实相当于渲染过程中的”钩子“,与熟悉的 created, mounted 一样。
完整的导航解析流程:
导航被触发。
在失活的组件里调用 beforeRouteLeave 守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
显然,这里使用 beforeRouteLeave 钩子就能很好地满足要求:
// 搜索结果页面
beforeRouteLeave(to, from, next) {
// vuex 存储操作
this.$store.commit("updateRevert", {
query: this.queryParam,
page: this.pageParam,
filter: this.filter,
});
next(); // 继续后续的导航解析过程
},
加载页面时检查是否有保存的参数,有的话进行相应恢复操作:
// 搜索结果页面
mounted() {
// 判断 vuex 中是否有保存的搜索参数
if (this.$store.state.revert) {
const revert = this.$store.state.revert;
this.queryParam = revert.query;
this.pageParam = revert.page; // 可以直接取出整个对象
// 搜索操作
} else {
// 没有搜索参数(因为我这搜索结果和主页是同一个页面,所以有可能只是正常打开主页)
}
},
结语
以上是两种保存页面状态方式的分享。其中很多选择是与当时的实际需求相关的,因此不一定在所有场景下都是最佳方案。对于你的具体需求,可能文中的方案可能存在不足,或者有更简单的方法;
感谢你的阅读,如果有什么问题,请在留言区给我留言。
学习更多技能
请点击下方公众号