前端开发过程中,有一些页面,当用户离开时,需要提醒用户确认是否离开,例如还未支付,提醒用户是否进行支付;我这里的场景是页面是一个大的表单,防止用户填写了很多内容,误触了其他页面,导致之前填写的内容丢失
一、效果
二、实现
由于这一块的逻辑相对独立,所有将这块逻辑抽离到mixin中
utils/backConfirm.js
import { mapState, mapMutations } from 'vuex'
/*
mixin使用说明:
1. 导入 import { confirmMixin } from '@/mixins/backConfirm'
2. 注册 mixins: [confirmMixin],
3. 需要在data中定义highlight属性,值为需要高亮的路由路径,如:highlight: '/product/product-add/type'
4. isSubmit参数控制是否需要在离开时给出二次提示,若为true,说明是点击提交按钮离开,此时不需要二次提示;
若为false,说明是点击浏览器的前进、后退按钮或者是点击其他的菜单栏离开,此时需要二次提示
*/
export const confirmMixin = {
computed: {
...mapState({
activeIndex: (state) => state.app.activeIndex,
activePath: (state) => state.app.activePath,
isSubmit: (state) => state.app.isSubmit
})
},
created() {
this.SET_IS_SUBMIT(false)
},
beforeRouteLeave(to, from, next) {
// history.pushState(null, null, window.location.href)
if (this.isSubmit) {
next() // 允许离开
} else {
const answer = window.confirm('确认离开,当前页面的信息将丢失')
if (answer) {
next() // 允许离开
} else {
next(false) // 阻止导航
this.SET_ACTIVE_INDEX(this.activeIndex + 1)
this.SET_ACTIVE_PATH(this.$options.data().highlight)
}
}
},
mounted() {
window.addEventListener('beforeunload', this.handleBeforeUnload)
},
beforeDestroy() {
window.removeEventListener('beforeunload', this.handleBeforeUnload)
},
methods: {
...mapMutations({
SET_ACTIVE_INDEX: 'app/SET_ACTIVE_INDEX',
SET_ACTIVE_PATH: 'app/SET_ACTIVE_PATH',
SET_IS_SUBMIT: 'app/SET_IS_SUBMIT'
}),
handleBeforeUnload(event) {
const message = '确认离开,当前页面的信息将丢失'
event.returnValue = message
return message
}
}
}
需要在state中定义好3个字段:
activeIndex: 0, // 每次从产品发布第二页(page2)离开时,如果点击取消,则将此参数加1;在Sidebar组件中,监听此参数,若发生变化,重置菜单栏的高亮为产品发布
activePath: '', // 需要高亮的菜单
isSubmit: false // 是否是点击提交按钮离开,默认为false,点击提交离开时设置为true
在mutations中定义3个方法:
SET_ACTIVE_INDEX: (state, num) => {
state.activeIndex = num
},
SET_ACTIVE_PATH: (state, path) => {
state.activePath = path
},
SET_IS_SUBMIT: (state, isSubmit) => {
state.isSubmit = isSubmit
}
使用mixin:mixins: [confirmMixin],
Sidebar组件:
这里是将菜单栏的高亮重置为当前页,需要用到activeIndex属性
给el-menu组件添加ref属性:ref="menuRef"
watch: {
// 每次离开产品发布第二页(page2)时,点击取消时,会触发activeIndex变化,此时需要重置菜单栏的高亮为产品发布
activeIndex: {
handler() {
this.$refs.menuRef.activeIndex = this.activePath
}
}
}
三、提示说明
- beforeRouteLeave钩子中,一开始是用的this.$confirm方法,但是这个方法在点击浏览器的后退按钮时,无法正常弹出,所以用window.confirm方法
- beforeunload事件,可以监听浏览器刷新及关闭窗口
如果你觉得这篇文章对你有用,可以看看作者封装的库xtt-utils,里面封装了非常实用的js方法。如果你也是vue开发者,那更好了,除了常用的api,还有大量的基于element-ui组件库二次封装的使用方法和自定义指令等,帮你提升开发效率。不定期更新,欢迎交流~