場景
在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"
});
},
結果:
image
第二個通知會覆蓋到第一個通知上邊,并沒有隔開間距
代碼分析
查看了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更新之后,在執行第二次通知的代碼,此時通知的高度就會計算正確
如圖:
image
這種解決方法有很大的局限性,實際業務場景中同時彈出的通知數量是不確定的,如果是三個、四個時該怎么寫?回調函數套回調函數么??
推薦解決辦法
由于對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條或任意多條通知顯示都正常,如圖:
image
如果哪位同學有更好的解決方法,請評論留言,謝謝
tips
本來想給element-ui提個issue,但是他們的github上要求在jsfiddle上創建重現的鏈接,但是我打不開jsfiddle的網站,只好作罷。。
哪位同學方便的話,請順手提交一下issue,希望后續的版本能直接支持這種場景