通过 Laravel 中的 websocket 收到通知后,Vue.js 组件未更新

Posted

技术标签:

【中文标题】通过 Laravel 中的 websocket 收到通知后,Vue.js 组件未更新【英文标题】:Vue.js component not updating after notification is received via websocket in Laravel 【发布时间】:2020-11-03 08:47:39 【问题描述】:

我正在尝试实时填充通知列表,但视图 vue 组件没有更新。到目前为止我的代码:

app.js

require('./bootstrap');
window.Vue = require('vue');

Vue.component('notification-alert', require('./components/NotificationAlert.vue').default);
Vue.component('notification-item', require('./components/NotificationItem.vue').default);

const app = new Vue(
    el: '#notification_alert',

    data: 
        notifications: [],
        notify_count: 0
    ,
    created() 
        this.fetchNotifications();
        this.checkNotifications();

        Vue.prototype.$userId = document.querySelector("meta[name='user-id']").getAttribute('content'),

        Echo.private('user.'+ this.$userId)
            .notification((notification) => 
                // console.log(notification); // This works perfectly fine, notification appear in Dev Console without reloading.
                this.notifications.push(notification);
                this.notify_count++;
           );
    ,
    methods: 
        fetchNotifications() 
            axios.get('/doc_booking/public/notification/data').then(response => 
                this.notifications = response.data;
            );
        ,
        checkNotifications()
            axios.get('/doc_booking/public/notification/check').then(response => 
                this.notify_count = response.data;
            );
        ,
    ,
);

NotificationItem.vue

<template>
    <ul class="menu list-unstyled">
        <li v-for="notification in notifications" v-if="notification.type === 'App\\Notifications\\OrderCancelled' || notification.type === 'App\Notifications\OrderAccepted' || notification.type === 'App\Notifications\OrderCompleted'">
            <a href="javascript:void(0);">
                <div class="icon-circle bg-warning" v-if="notification.type === 'App\\Notifications\\OrderCancelled' && (notification.data.cancel_type === 1 || notification.data.cancel_type === 2)"><i class="zmdi zmdi-close"></i></div>
                <div class="icon-circle bg-danger" v-if="notification.type === 'App\\Notifications\\OrderCancelled' && notification.data.cancel_type === 3"><i class="zmdi zmdi-delete"></i></div>
                <div class="icon-circle bg-primary" v-if="notification.type === 'App\\Notifications\\OrderAccepted'"><i class="zmdi zmdi-check"></i></div>
                <div class="icon-circle bg-green" v-if="notification.type === 'App\\Notifications\\OrderCompleted'"><i class="zmdi zmdi-case-check"></i></div>
                <div class="menu-info">
                    <h4 v-if="notification.type === 'App\\Notifications\\OrderCancelled' && notification.data.cancel_type === 1">Order Cancelled By Notary:  notification.data.order_id </h4>
                    <h4 v-if="notification.type === 'App\\Notifications\\OrderCancelled' && notification.data.cancel_type === 2">Order Cancelled:  notification.data.order_id </h4>
                    <h4 v-if="notification.type === 'App\\Notifications\\OrderCancelled' && notification.data.cancel_type === 3">Order Deleted:  notification.data.order_id </h4>
                    <h4 v-if="notification.type === 'App\\Notifications\\OrderAccepted'">Order Accepted:  notification.data.order_id </h4>
                    <h4 v-if="notification.type === 'App\\Notifications\\OrderCompleted'">Order Completed:  notification.data.order_id </h4>
                </div>
            </a>
        </li>
    </ul>
</template>
<script>
    export default 
        props: ['notifications'],
    ;
</script>

NotificationAlert.vue

<template>
    <div class="notify" v-if="notify_count > 0"><span class="heartbit"></span><span class="point"></span></div>
    <div class="notify" v-else></div>
</template>

<script>
    export default 
        props: ['notify_count']
    ;
</script>

在我的刀片文件中,我将其用作

<notification-alert :notify_count="notify_count"></notification-alert>

<notification-item :notifications="notifications"></notification-item>

除了实时更新外,其他一切正常。如果我正确获取刷新通知并正确显示通知警报。但是当通知事件发生时,通知不会在不重新加载的情况下呈现在视图上,但是如果我在控制台中打印通知对象,它工作得很好。任何建议或帮助将不胜感激。谢谢

【问题讨论】:

websocket函数运行时notify_count属性会改变吗? @Hiws 只要我们在控制台中打印,一切都会发生变化,但它们不会在视图中呈现。 好吧,只是想看看它是否只是数组,或者notify_count 是否也没有反应。只想确认一下。如果你在函数内部做console.log(this.notifications),它会返回数组吗?您也可以尝试使用v-for 将key 添加到li 我添加了关键属性,但仍然没有进展。 &lt;li v-for="notification in notifications" v-bind:key="notification.id" ... 抱歉,我没办法了:/ 【参考方案1】:

在您的 Echo.private() 块中,尝试更改

this.notifications.push(notification);

this.notifications = [...this.notifications, notification];

这可能是reactivity 问题。新代码做同样的事情,但将整个数组重写为 data 属性。

【讨论】:

是的,我试过了,但是没有用。我按照你提到的链接,尝试了this.notifications..splice(0,0,notification);,但也没有用。

以上是关于通过 Laravel 中的 websocket 收到通知后,Vue.js 组件未更新的主要内容,如果未能解决你的问题,请参考以下文章

500内部错误Laravel,通过websocket守护进程获取图像

websocket前端发送一个消息 后端还没执行完 收不到第二条消息

JAVA socket 收不到数据 求指点

AWS 中的 Laravel WebSockets 推送器

宅基地中的laravel websocket无法正常工作

为啥火币服务器收不到 C# WebSocket Ping?