You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js聊天消息系统:如何为对方用户添加/移除unread类实现已读未读功能

嘿,我来帮你搞定这个Vue聊天系统的未读消息标记问题!咱们一步步拆解需求,逐个解决:

1. 给对方聊天元素添加unread类的基础逻辑

首先得明确每条消息的归属——你的每条消息数据里应该有user_id(发送者ID)和seen(是否已读)字段对吧?在渲染消息的模板(chat.blade.php里的Vue部分),我们可以通过条件判断给对方的未读消息加上类:

<!-- 假设你的消息循环是这样的 -->
<div 
  v-for="message in messages" 
  :key="message.id"
  :class="[
    'chat-message', 
    // 如果是对方发的+未读,就加unread类
    message.user_id !== currentUserId && !message.seen ? 'unread' : ''
  ]"
>
  <!-- 消息内容、头像等 -->
  <p>{{ message.content }}</p>
</div>

这里的currentUserId要绑定当前登录用户的ID(比如从blade模板传值给Vue:currentUserId: {{ auth()->id() }})。

2. 实时发消息时给对方自动加unread类

假设你用了Laravel Echo这类实时工具(毕竟是blade模板,大概率是Laravel+Vue栈),当你发送消息后,后端广播MessageSent事件,对方前端监听这个事件时,直接把新消息标记为未读再加入列表:

// App.js 里的实时监听逻辑
Echo.channel(`chat.${this.conversationId}`)
  .listen('MessageSent', (event) => {
    // 只处理对方发的消息
    if (event.message.user_id !== this.currentUserId) {
      // 标记为未读,这样上面的类判断会自动生效
      event.message.seen = false;
      this.messages.push(event.message);
      // 可选:自动滚动到最新消息
      this.scrollToBottom();
    }
  });

后端的MessageSent事件要确保传递完整的消息对象,包含user_id字段哦。

3. 对方点击文本框时移除unread类+标记已读

给输入框绑定focus事件,触发标记已读的方法:

<!-- chat.blade.php 里的输入框 -->
<textarea 
  v-model="newMessage" 
  @focus="markAllUnreadAsRead"
  placeholder="输入消息..."
></textarea>

然后在App.js里实现这个方法,要做三件事:筛选未读消息、调用后端接口标记、更新前端状态,还要通知对方同步:

// App.js 里的methods
async markAllUnreadAsRead() {
  // 筛选出对方发的未读消息ID
  const unreadIds = this.messages
    .filter(msg => msg.user_id !== this.currentUserId && !msg.seen)
    .map(msg => msg.id);

  if (unreadIds.length === 0) return; // 没有未读就直接返回

  // 调用你的seen接口(后端批量标记已读)
  await axios.post('/chat/mark-seen', {
    message_ids: unreadIds,
    conversation_id: this.conversationId
  });

  // 更新前端消息的已读状态,自动移除unread类
  this.messages.forEach(msg => {
    if (unreadIds.includes(msg.id)) {
      msg.seen = true;
    }
  });

  // 给对方发个实时通知,让他那边也同步已读状态
  Echo.channel(`chat.${this.conversationId}`)
    .whisper('messagesMarkedAsRead', {
      message_ids: unreadIds,
      user_id: this.currentUserId
    });
}

然后发送方要监听这个实时通知,更新自己这边的消息状态:

// App.js 里继续监听
Echo.channel(`chat.${this.conversationId}`)
  .listenForWhisper('messagesMarkedAsRead', (data) => {
    // 只处理自己发的消息被标记已读的情况
    if (data.user_id !== this.currentUserId) {
      this.messages.forEach(msg => {
        if (data.message_ids.includes(msg.id)) {
          msg.seen = true;
        }
      });
    }
  });
4. 双方同步隐藏未读标识

不管是聊天列表的小红点还是会话内的未读计数,都可以通过计算属性实时计算:

// App.js 里的computed
computed: {
  unreadCount() {
    return this.messages.filter(msg => msg.user_id !== this.currentUserId && !msg.seen).length;
  }
}

然后在模板里根据计数显示/隐藏标识:

<!-- 比如聊天列表里的未读徽章 -->
<span v-if="unreadCount > 0" class="unread-badge">{{ unreadCount }}</span>

这样不管是实时收到消息增加计数,还是标记已读后减少计数,双方的界面都会自动同步更新。

最后提醒下:你的后端seen函数要支持批量标记消息为已读,并且返回成功响应,确保前端能正确触发状态更新~

内容的提问来源于stack exchange,提问作者Jadasdas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:10:51