今日の開発中に次の問題が発生しました。
シーン:
配列があるので、element-ui の Notice コンポーネントを使用して、配列を走査し、ページの右下隅に配列内の各項目をレンダリングする必要があります。
これは単純ではありません。arr.forEach() で実行できます。!!
tipsArr.forEach((item: string) => {
this.$notify({
title: item,
message: '',
position: 'bottom-right',
type: 'warning',
duration: 0,
offset: 10
});
})
しかし、コードを書いた後のページ表示はこんな感じだったり、各情報が重なっていたり、公式サイトの表示と効果が違ったりで、思ったよりうまくいかないようです?? ?
リマインダー メッセージがすべて重なっています。1 つのメッセージを閉じないと次のメッセージの内容が表示されません。これは私が望んでいる効果ではありません。!!公式サイトにあるようにタイル化できるといいですね。
原因分析:
その後、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 になります。 2 番目の通知はすべて上に移動されます。デフォルトの 16 ピクセルのオフセットでは、最初の通知の高さは追加されません。後続の通知ごとに 16 ピクセルの間隔が増加するだけです。最終的にレンダリングされた通知コンポーネントは重なり合います。
解決:
方法 1: nextTick メソッドを使用する
ただし、この方法には一定の制限があります。つまり、表示される通知メッセージが少数であることがわかっている、または配列の長さがわかっていて、配列の長さの値がそれほど長くないことがわかっている必要があります。
//已知 tipsArr的length值为2
this.$notify({
title: tipsArr[0],
message: '',
position: 'bottom-right',
type: 'warning',
duration: 0,
offset: 10
});
this.$nextTick(() => {
this.$notify({
title: tipsArr[1],
message: '',
position: 'bottom-right',
type: 'warning',
duration: 0,
offset: 10
});
})
方法 2: setTimeout を使用する
data() {
return {
timer: null
}
},
tipsArr.forEach((item: string) => {
this.timer = setTimeout(() => {
this.$notify({
title: item,
message: '',
position: 'bottom-right',
type: 'warning',
duration: 0,
offset: 10
});
}, 0)
this.$once('hook:beforeDestroy', () => {
this.timer && clearTimeout(this.timer)
this.timer = null
})
})
方法 3: Promise を使用する
data() {
return {
notifyPromise: Promise.resolve()
}
}
tipsArr.forEach((item: string) => {
this.notifyPromise = this.notifyPromise.then(() => {
this.$notify({
title: item,
message: '',
position: 'bottom-right',
type: 'warning',
duration: 0,
offset: 10
});
})
})