场景
在1个方法中调用两次this.$notify方法,会出现通知框重叠的问题
代码
testNotify() {
this.$notify({
title: "提示",
message: '1111',
dangerouslyUseHTMLString: true,
duration: 0,
position: "bottom-right"
});
this.$notify({
title: "提示",
message: '2222',
dangerouslyUseHTMLString: true,
duration: 0,
position: "bottom-right"
});
},
结果:
第二个通知会覆盖到第一个通知上边,并没有隔开间距
代码分析
查看了notify的源码,找到了原因
let verticalOffset = options.offset || 0;
instances.filter(item => item.position === position).forEach(item => {
verticalOffset += item.$el.offsetHeight + 16;
});
verticalOffset += 16;
instance.verticalOffset = verticalOffset;
计算通知的间距时,会取当前元素的高度 item.$el.offsetHeight ,但是因为vue的异步更新队列有缓冲机制,第一次方法调用时,并没有更新dom,导致取到的高度为0,所有第二个通知只是上移了默认的offset 16px,并没有加上第一个通知的高度
vue 异步更新队列文档
解决办法
有局限的解决办法
最简单的解决办法就是使用vue提供的nextTick方法,将上述代码改为如下:
testNotify() {
this.$notify({
title: "提示",
message: "1111",
dangerouslyUseHTMLString: true,
duration: 0,
position: "bottom-right"
});
this.$nextTick(() => {
this.$notify({
title: "提示",
message: "2222",
dangerouslyUseHTMLString: true,
duration: 0,
position: "bottom-right"
});
});
},
第一次通知调用完之后,在nextTick的回调函数中执行第二次通知的调用,保证第一次通知的dom更新之后,在执行第二次通知的代码,此时通知的高度就会计算正确
如图:
这种解决方法有很大的局限性,实际业务场景中同时弹出的通知数量是不确定的,如果是三个、四个时该怎么写?回调函数套回调函数么??
推荐解决办法
由于对Promise理解的也不是很透彻,折腾了一下午算是想了个通用点的解决办法
data(){
return {
notifyPromise:Promise.resolve()
}
},
methods:{
notify(){
//通知,解决element-ui,同时调用notify时,通知重叠的问题
notify(msg) {
this.notifyPromise = this.notifyPromise.then(this.$nextTick).then(()=>{
this.$notify({
title: "提示",
message: msg,
dangerouslyUseHTMLString: true,
duration: 0,
position: "bottom-right"
});
})
}
},
testNotify(){
this.notify(111);
this.notify(222);
this.notify(333);
this.notify(444);
}
}
注意:this.$nextTick()不传回调函数时返回的是个Promise
执行testNotify方法后,1条或任意多条通知显示都正常,如图:
如果哪位同学有更好的解决方法,请评论留言,谢谢
tips
本来想给element-ui提个issue,但是他们的github上要求在jsfiddle上创建重现的链接,但是我打不开jsfiddle的网站,只好作罢。。
哪位同学方便的话,请顺手提交一下issue,希望后续的版本能直接支持这种场景