5

我正在构建一个通知系统,它可以正常工作,但不能正常工作。我有以下组合功能

const data = reactive({
    notifications: []
});
let notificationKey = 0;

export const useNotification = () => {
    const visibleNotifications = computed(() => {
        return data.notifications.slice().reverse();
    });

    const add = (notification: INotification) => {
        notification.key  = notificationKey++;
        notification.type = notification.type ?? 'success';

        notification.icon      = iconObject[notification.type];
        notification.iconColor = iconColorObject[notification.type];
        data.notifications.push(notification);

        notificationTimer[notification.key] = new Timer(() => {
            remove(notification.key);
        }, notificationTimeout);
    };

    const remove = (notificationKey: number) => {
        const notificationIndex = data.notifications.findIndex(notification => notification?.key === notificationKey);
        if (notificationTimer[notificationKey] !== undefined) {
            notificationTimer[notificationKey].stop();
        }
        if (notificationIndex > -1) {
            data.notifications.splice(notificationIndex, 1);
        }
    };

    const click = (notification: INotification) => {
       /// ... click code 
    };

    return {
        visibleNotifications,
        add,
        remove,
        click
    };
};

这是有效的(它被简化了一点)。现在,我在 Webpack 中有两个入口点。在一个入口点 (auth) 中,我有以下代码来加载 Vue 组件以显示通知

 Promise.all([
    import(/* webpackChunkName: "Vue"*/ 'vue'),
    import(/* webpackChunkName: "@vue/composition-api"*/ '@vue/composition-api'),
    import(/* webpackChunkName: "Notifications"*/'components/Notifications.vue')
]).then((
    [
        { default: Vue },
        { default: VueCompositionAPI },
        { default: Notifications },
    ]) => {
    Vue.use(VueCompositionAPI);

    new Vue({
        render: h => h(Notifications)
    }).$mount('.notification-outer);
});

现在,这一切都有效,我在其中添加了以下代码

import { useNotification } from 'modules/compositionFunctions/notifications';
useNotification().add({
    title  : 'Error',
    message: 'This is an error notification',
    type   : 'error',
});

然后通知按预期显示通知图片这一切都发生在“auth”入口点内部,以上都是打字稿。

现在,如果我转到我的第二个入口点(编辑器),并在现有的 JS 文件中输入以下代码

import(/* webpackChunkName: "useNotification"*/ 'modules/compositionFunctions/notifications').then(({ useNotification }) => {
    useNotification().add({
        title     : 'Block Deleted',
        message   : 'The block has been deleted',
        buttonText: 'Undo',
        buttonFunction () {
            undoDelete();
        }
    });
});

然后它“工作”,我的意思是,useNotification 函数中的所有代码都工作。add 方法将添加它,(如果我控制台注销响应属性),并且在 15000 毫秒后,删除方法发生,我可以添加日志来显示这一点。但是,Vue 组件永远不会看到这种变化。如果我在 Vue 组件中添加一个手表,然后退出,第一个通知(上图)将使 JS 登录到控制台,但是,当从“编辑器”入口点添加它时,它不会做任何事物。

Vue 组件 JS

import { useNotification } from 'modules/compositionFunctions/notifications';
import { defineComponent } from '@vue/composition-api';

export default defineComponent({
    name : 'Notifications',
    setup () {
        const { visibleNotifications, remove, click: notificationClick } = useNotification();

        return {
            visibleNotifications,
            remove,
            notificationClick,
        };
    },
    watch: {
        visibleNotifications: (v) => {
            console.log(v);
        }
    }
});

请有人告诉我他们可以帮忙吗?这开始让我头疼了……

TIA

4

2 回答 2

1

使用 GitHub 存储库中提供的代码,我在这部分之前添加了一些控制台日志记录:

window.notifications = reactive({
   notifications: []
});

日志记录被调用了两次。一次从entry1.hash.bundle.js一次从entry2.hash.bundle.js

我对 Webpack 的理解是有限的,但它似乎将这两个入口点构建为自包含的,并且不希望您同时在页面上运行它们。

我原以为可以将所有通知内容提取到自己的共享块中,有点像供应商捆绑包。也就是说,我不太清楚为什么您使用两个入口点而不是两个块。我的理解是入口点应该是每页一个,然后你使用块将它们拆分。

综上所述,有一个快速的技巧可以让它工作:

if (!window.notifications) {
    window.notifications = reactive({
        notifications: []
    });
}

这样可以确保无论运行多少次,都可以共享同一个数组。

我应该强调的是,我不提倡在生产代码中使用这种 hack。它只是进一步解决了 Webpack 问题,并在此过程中污染了全局命名空间。它确实有助于确认问题所在。

于 2020-09-04T01:15:00.907 回答
0

我从您的代码中推断出,您的组件是紧密耦合的。我建议遵循更面向对象的方法,例如 user->data->notification->seen 等等。这可能需要对数据库中的现有代码(和或)进行轻微重组。

我还建议你看看 firebase(FCM Firebase Cloud Messaging)。一个通知系统。firebase 是谷歌的产品,可以信任他们的方法。(不是推广它,但他们实现通知系统的方式是绝对可扩展的)

但如果它是一个完全自行开发的应用程序并且不想依赖第三方,那么下一个最佳举措是使用“通知更改”方法。

粗略的概述将是这样的。

  • 数据库/应用程序中的某些事件(需要通知用户)发生
  • 追踪事件对受影响用户的影响[事件范围]
  • 建立一个通知对象[一些 json 文件] 存储在数据库或普通 json 中,例如notif.json
  • 现在,一旦用户处于活动状态,就将其发送给用户。

您可以通过客户端的 setInterval() 函数检查它们是否处于活动状态。一旦它们处于活动状态,请检查 notif.json,如果它有待处理的通知,请将其推送给用户并从文件或数据库中删除该条目。

经验法则是,如果现有代码不起作用,则不要在现有代码中浪费时间,有时以不同的方法重写可以节省更多时间。

于 2020-09-03T03:43:49.530 回答