我尝试实施一个简单的通知系统,其中包含受此片段形式Linus Borg启发的通知商店:https://jsfiddle.net/Linusborg/wnb6tdg8/
当您一次添加一个通知时它工作正常,但是当您在第一个通知消失之前添加第二个通知时,notificationMessage会发出" close-notification"事件但父通知组件组件不执行" removeNotification"功能。如果您在通知上使用click事件,则会在emit之后调用removeNotification。因此,超时可能存在问题,但我无法弄清楚是什么。
NotificationStore.js
class NotificationStore {
constructor () {
this.state = {
notifications: []
}
}
addNotification (notification) {
this.state.notifications.push(notification)
}
removeNotification (notification) {
console.log('remove from store')
this.state.notifications.splice(this.state.notifications.indexOf(notification), 1)
}
}
export default new NotificationStore()
App.vue
<template>
<div id="app">
<notification-box></notification-box>
<div @click="createNotif">
create new notification
</div>
</div>
</template>
<script>
import notificationMessage from './components/notificationMessage.vue'
import notificationBox from './components/notificationBox.vue'
import NotificationStore from './notificationStore'
export default {
name: 'app',
methods: {
createNotif () {
NotificationStore.addNotification({
name: 'test',
message: 'this is a test notification',
type: 'warning'
})
}
},
components: {
notificationMessage,
notificationBox
}
}
</script>
notificationBox.vue
<template>
<div :class="'notification-box'">
<notification-message v-for="(notification, index) in notifications" :notification="notification" :key="index" v-on:closeNotification="removeNotification"></notification-message>
</div>
</template>
<script>
import notificationMessage from './notificationMessage.vue'
import NotificationStore from '../notificationStore'
export default {
name: 'notificationBox',
data () {
return {
notifications: NotificationStore.state.notifications
}
},
methods: {
removeNotification: function (notification) {
console.log('removeNotification')
NotificationStore.removeNotification(notification)
}
},
components: {
notificationMessage
}
}
</script>
notificationMessage.vue
<template>
<div :class="'notification-message ' + notification.type" @click="triggerClose(notification)">
{{ notification.message }}
</div>
</template>
<script>
export default {
name: 'notificationMessage',
props: {
notification: {
type: Object,
required: true
},
delay: {
type: Number,
required: false,
default () {
return 3000
}
}
},
data () {
return {
notificationTimer: null
}
},
methods: {
triggerClose (notification) {
console.log('triggerClose')
clearTimeout(this.notificationTimer)
this.$emit('closeNotification', notification)
}
},
mounted () {
this.notificationTimer = setTimeout(() => {
console.log('call trigger close ' + this.notification.name)
this.triggerClose(this.notification)
}, this.delay)
}
}
</script>
感谢您的帮助
答案 0 :(得分:2)
我在后面的那个小小提琴仍在进行我看到的回合:D
这个小提琴仍在使用Vue 1.在Vue 2中,你必须键入你的列表元素,你试图这样做。
但是key
应该是一个可靠地标识数据项的唯一值。您正在使用不执行此操作的数组索引 - 只要删除元素,就会更改以下项的索引。
这就是为什么你看到你所看到的行为:Vue无法可靠地删除正确的元素,因为我们的密钥不起作用。
所以我建议使用像nanoid
之类的包来为每个通知创建一个真正唯一的ID - 但是一个简单的计数器可能也会起作用:
let _id = 0
class NotificationStore {
constructor () {
this.state = {
notifications: []
}
}
addNotification (notification) {
this.state.notifications.push({ ...notification, id: _id++ })
}
removeNotification (notification) {
console.log('remove from store')
this.state.notifications.splice(this.state.notifications.indexOf(notification), 1)
}
}
并在通知组件中:
<notification-message
v-for="(notification, index) in notifications"
:notification="notification"
:key="notification.id"
v-on:closeNotification="removeNotification"
></notification-message>