在短时间内多次调用时,家长未收到vue.js$emit

在短时间内多次调用时,家长未收到vue.js$emit,vue.js,vuejs2,settimeout,Vue.js,Vuejs2,Settimeout,我试图用通知存储实现一个简单的通知系统,其灵感来源于Linus Borg的这段代码: 一次添加一个通知可以正常工作,但在第一个通知消失之前添加第二个通知时,notificationMessage会发出“关闭通知”事件,但父notificationBox组件不会执行“removeNotification”功能。如果在通知上使用click事件,则会在发出后调用removeNotification。所以超时可能有问题,但我不知道是什么 NotificationStore.js class Notifi

我试图用通知存储实现一个简单的通知系统,其灵感来源于Linus Borg的这段代码:

一次添加一个通知可以正常工作,但在第一个通知消失之前添加第二个通知时,notificationMessage会发出“关闭通知”事件,但父notificationBox组件不会执行“removeNotification”功能。如果在通知上使用click事件,则会在发出后调用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>

创建新通知
从“./components/notificationMessage.vue”导入notificationMessage
从“./components/notificationBox.vue”导入notificationBox
从“./NotificationStore”导入NotificationStore
导出默认值{
名称:“应用程序”,
方法:{
createNotif(){
NotificationStore.addNotification({
名称:'测试',
消息:“这是一个测试通知”,
类型:“警告”
})
}
},
组成部分:{
通知信息,
通知箱
}
}
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”导入notificationMessage
从“../NotificationStore”导入NotificationStore
导出默认值{
名称:'notificationBox',
数据(){
返回{
通知:NotificationStore.state.notifications
}
},
方法:{
removeNotification:功能(通知){
console.log('removeNotification')
NotificationStore.removeNotification(通知)
}
},
组成部分:{
通知信息
}
}
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>

{{notification.message}}
导出默认值{
名称:“notificationMessage”,
道具:{
通知:{
类型:对象,
必填项:true
},
延迟:{
类型:数字,
必填项:false,
默认值(){
返回3000
}
}
},
数据(){
返回{
notificationTimer:空
}
},    
方法:{
触发关闭(通知){
console.log('triggerClose')
clearTimeout(此.notificationTimer)
此.$emit('closeNotification',notification)
}
},
挂载(){
this.notificationTimer=setTimeout(()=>{
console.log('call trigger close'+this.notification.name)
this.triggerClose(this.notification)
},这个。延迟)
}
}

谢谢你的帮助

我以前的小提琴仍然在我看到的地方演奏:D

那把小提琴仍在使用Vue 1。在Vue 2中,您必须为列表元素设置关键帧,并且您已经尝试过这样做

但是,
应该是可靠地标识数据项的唯一值。您使用的是数组索引,而数组索引并没有做到这一点——一旦删除一个元素,以下项目的索引就会改变

这就是为什么您会看到所看到的行为:Vue无法可靠地删除正确的元素,因为我们的键不起作用

因此,我建议使用一个包,比如为每个通知创建一个真正唯一的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>

我以前的小提琴仍然在我看到的地方演奏:D

那把小提琴仍在使用Vue 1。在Vue 2中,您必须为列表元素设置关键帧,并且您已经尝试过这样做

但是,
应该是可靠地标识数据项的唯一值。您使用的是数组索引,而数组索引并没有做到这一点——一旦删除一个元素,以下项目的索引就会改变

这就是为什么您会看到所看到的行为:Vue无法可靠地删除正确的元素,因为我们的键不起作用

因此,我建议使用一个包,比如为每个通知创建一个真正唯一的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>


非常感谢您的帮助:)以及初始代码。非常感谢您的帮助:)以及初始代码。