最近项目中遇到了一个需求:在下单页中的底部弹层使我们的组件,以解耦的方式运行在别的项目组的页面中(下单页),此时在弹层出来的时候,使用物理返回,就会跳转到“确认订单”页面的上一个页面,不符合操作逻辑。
✋ 本次优化:在使用物理返回的时候,只触发组件的返回组件的上一级,不要触发页面级别的后退。
1. 方案1:使用 vue-router 的 beforeRouteLeave
实验代码最初想的方案的确就是
beforeRouteLeave
,但是实现起来的时候,发现好像没有效果,根本控制不住router的变化。后来实验了一波,发现这个钩子只能作用在router指定路由时的页面上,而该页面的组件如果使用该钩子,是没有效果的,下面是实验的代码:
2. 方案2: 自己设置history.state(因为我们的路由采用的是history模式),自己监听popstate,自己编写业务代码触发。
(1)工具类
const HISTORY_STATE = '_history_state_mutou_'
/**
* 页面记录栈
*/
class PageStack {
constructor() {
// 本地存储一份记录,因为history在pop的时候,得不到是哪一条记录被pop掉了
this.localStack = []
}
/**
* 获取history中的栈
*/
getHistoryStack() {
return get(history, `state.${HISTORY_STATE}`, [])
}
/**
* 向栈中压入一条记录
* @param {*} name 记录名称
*/
pushState(name) {
if (this.localStack.includes(name)) {
return
}
this.localStack.push(name)
history.pushState(
{ ...(history.state || {}), [HISTORY_STATE]: this.localStack },
document.title
);
}
/**
* 触发history的pop
*/
popState() {
history.go(-1)
}
/**
* 开启监听
* @param {*} callback 回调
*/
observePop(callback) {
const listener = (event) => {
const popName = this.localStack.pop()
callback(popName)
}
window.addEventListener('popstate', listener)
return () => {
window.removeEventListener('popstate', listener)
const length = this.localStack.length
length && window.history.go(-length)
this.localStack = []
}
}
}
export const pageStack = new PageStack()
(2)在业务中使用
mounted() {
pageStack.pushState(PAGE_STACK_NAMES.ONE_PAGE)
this.clearPageListener = pageStack.observePop((name) => {
if (name === PAGE_STACK_NAMES.TWO_PAGE) {
// 触发事件...
}
if (name === PAGE_STACK_NAMES.ONE_PAGE) {
// 触发事件...
}
})
},
beforeDestroy() {
this.clearPageListener && this.clearPageListener()
},
以上大概就是实现的方式的代码,逻辑其实并不复杂,使用history的特性做了一些代码封装,让其好使一些。
参考资料:
https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState
网友评论