【发布时间】:2021-10-13 22:52:14
【问题描述】:
我正在尝试使用内置的 Vuex 商店在 Nuxt 中制作一个通知组件。我有两个组件,Notifications.vue 和 Notification.vue 来显示通知。我的商店有两个突变,一个用于添加通知,另一个用于删除一个。
以下是我项目中的相关文件:
store/notifications.js
export const state = () => ({
notifications: []
});
export const getters = {
allNotifications: state => state.notifications
};
export const mutations = {
PUSH_NOTIFICATION(state, notification) {
state.notifications.push(notification);
},
REMOVE_NOTIFICATION(state, notificationToRemove) {
// PROBLEM ---> Updates state but breaks reactivity
state.notifications = [
...state.notifications.filter(notification => notification.id != notificationToRemove)
];
};
export const actions = {
async pushNotification({ commit }, notification) {
return new Promise((resolve, reject) => {
notification = {
...notification,
id: (Math.random().toString(36) + Date.now().toString(36)).substr(2)
};
commit('PUSH_NOTIFICATION', notification);
resolve(notification.id);
});
},
async removeNotification({ commit }, id) {
return new Promise((resolve, reject) => {
commit('REMOVE_NOTIFICATION', id);
resolve();
});
}
};
plugins/notifications.js
export default ({ store }, inject) => {
let notifications = {
async notify(notification) {
return await store.dispatch('notifications/pushNotification', notification);
},
async removeNotification(id) {
console.log(`The notification with the id ${id} will be removed!`);
await store.dispatch('notifications/removeNotification', id);
return true;
}
};
// This allows me to access the methods above from any component like `this.$notifications`
inject('notifications', notifications);
};
components/Notifications.vue
<template>
<div class="notifications">
<button @click="test()">Notify</button><!-- This is to test adding new notifications -->
<div class="notification-bounds">
<Notification v-for="notification in notifications" :key="notification.id" :id="notification.id">{{ notification.content }}</Notification>
</div>
</div>
</template>
<script>
export default {
data() {
return {
notifications: this.$store.getters['notifications/allNotifications']
};
},
methods: {
test() {
// This works therefore `PUSH_NOTIFICATION` does not break reactivity
this.$notifications.notify({ content: 'Test' });
}
}
};
</script>
components/Notification.vue
<template>
<div class="notification">
<slot></slot>
<button @click="close()">Close</button>
</div>
</template>
<script>
export default {
props: [
'id'
],
methods: {
close(){
// PROBLEM ---> This updates the state internally but it breaks reactivity so
// there is something wrong with the `REMOVE_NOTIFICATION` mutation.
this.$notifications.removeNotification(this.id)
}
}
};
</script>
问题在于REMOVE_NOTIFICATION 突变破坏了Notifications.vue 中v-for 的反应性。我该如何解决这个问题?
【问题讨论】:
-
弄清楚所有这些逻辑的问题是什么而不是“破坏反应性”的视觉指示有点复杂。同时,由于您在 Nuxt 后面使用 Vue2,您可能在数组警告中? vuejs.org/v2/guide/reactivity.html#For-Arrays
-
@kissu 我不认为我在数组警告范围内,因为我没有设置
notifications数组的特定属性,也没有像state.notifications.length = newLength那样更改它的长度。我只是将notifications数组设置为filter方法返回的新数组。我觉得就好像我在REMOVE_NOTIFICATION:state.notifications = newNotificationsArray做这个。 -
@kissu 顺便说一句,当我说“破坏反应性”时,我的意思是
REMOVE_NOTIFICATION正确地改变了状态(我可以通过在返回的浏览器控制台中调用window.$nuxt.$store.getters['notifications/allNotifications'];来验证这一点更新状态正确。)但更改未反映在浏览器页面中,因此当我删除通知时,浏览器不会从页面中删除相应的Notification组件。
标签: vue.js nuxt.js state vuex store