背景: 1. 这几天遇到个小需求:用户填写表单未保存,点击其他按钮,提示是否保存。如果否,离开当前页面并进行下一步
-
当产品提出这个需求后,我内心毫无波澜,心里想,这不是很简单吗~~~ 直接用 vue-router 的组件内守卫 beforeRouteLeave 不就行了。然而,还是太年轻了。所以,在这里总结下,给自己留个记录。
-
项目简介:我们的项目是基于vue全家桶开发后打包静态文件和elector打包成app的项目。对于本次需求到的页面,布局如下:传统的布局。用户在内容区3填写表单后,点击1 2 区域,需要提示用户是否保存。
-
刚开始我的开发想法,直接调用vue-router 的组件内守卫,离开时判断即可,然而,事情没有这莫简单~~ : beforeRouteLeave 只能在路由离开前“截住”路由的改变。
-
而我们的项目,左边列表区2 和头部菜单 区域1 的点击都会修改 vuex的状态,导致区域三的基础数据发生改变,从而引发请求刷新内容区。
也就是说:beforeRouteLeave 不能达到想要的效果。 因为beforeRouteLeave无法阻止js触发的事件。想要阻止事件的进行,相信自然而然都能想到:捕获 与 冒泡。但是新的问题又来了。就算阻止了事件的进行,那需求里面的并进行下一步该怎么处理?
我的想法是:在阻止事件传播时,记录下事件的 event,当用户确认不保存取消,再继续让event的targrt来执行刚才的事件。
具体做法:
- 在vuex里面增加状态变量A,标识是否表单数据被修改
- 在区域1 2 的最外层,绑定函数,执行事件捕获,函数里面根据A来确定,是否阻止冒泡。如果点击了1 2 区域,进行下一步。
- 判断是否表单数据被修改,修改了则分发中央事件,传递参数event,让内容区自己处理提示弹框,待用户确认。
verifyProjuctDataHandler(e){
if(A){
e.stopPropagation()
console.log('分发点击其他区域事件');
window.eventHub.$emit('clickOtherArea', e)
return false
}
},
4.如果用户点击了取消,执行对应的操作,并执行需求并进行下一步 用分发的事件的event,获取到的点击坐标,并模拟操作。达到效果:模拟事件暂停并继续执行。
// 模拟鼠标点击坐标(x,y)
function clickPoint(x, y){
var ev = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true,
'clientX': x,
'clientY': y });
var el = document.elementFromPoint(x, y);
el.dispatchEvent(ev);
}
至此,需求基本开发完成。如果有大佬有更好的解决思路,欢迎留言~~~