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

如何动态使用MDBootstrap Chat组件?

问题:MDBootstrap 5聊天功能需刷新页面才生效(已用SignalR后端)

我在应用中使用MDBootstrap 5的聊天功能,基于官方聊天扩展模板编写了代码,但即便后端用了SignalR,仍必须刷新页面才能让聊天内容更新。

模板代码如下:

<section style="background-color: #eee;">
  <div class="container py-5">

    <div class="row d-flex justify-content-center">
      <div class="col-md-10 col-lg-8 col-xl-6">

        <div class="card" id="chat2">
          <div class="card-header d-flex justify-content-between align-items-center p-3">
            <h5 class="mb-0">Chat</h5>
            <button type="button" class="btn btn-primary btn-sm" data-mdb-ripple-color="dark">
              Let's Chat
              App
            </button>
          </div>
          <div class="card-body" data-mdb-perfect-scrollbar="true" style="position: relative; height: 400px">

            <div *ngFor="let message of (messageService.messageThread$ | async)">

              <ng-container *ngIf="message.senderUsername !== currentUser!.userName">

                <div class="d-flex flex-row justify-content-start">
                  <img src="https://mdbcdn.b-cdn.net/img/Photos/new-templates/bootstrap-chat/ava3-bg.webp"
                       alt="avatar 1" style="width: 45px; height: 100%;">
                  <div>
                    <p class="small p-2 ms-3 mb-1 rounded-3" style="background-color: #f5f6f7;">ouweee {{message.content}}</p>
                    <p class="small ms-3 mb-3 rounded-3 text-muted">{{message.messageSent | date:'medium'}}</p>
                    <span class="text-danger" *ngIf="!message.dateRead">(unread)</span>
                    <span class="text-success" *ngIf="message.dateRead">(read {{message.dateRead + 'Z' | timeago}})</span>
                  </div>
                </div>

              </ng-container>

              <ng-container *ngIf="message.senderUsername === currentUser!.userName">
                <div class="d-flex flex-row justify-content-end mb-4 pt-1">
                  <div>
                    <p class="small p-2 me-3 mb-1 text-white rounded-3 bg-primary"> Nouwweee {{message.content}}</p>
                    <p class="small me-3 mb-3 rounded-3 text-muted d-flex justify-content-end">{{message.messageSent | date:'medium'}}</p>
                    <span class="text-danger" *ngIf="!message.dateRead">(unread)</span>
                    <span class="text-success" *ngIf="message.dateRead">(read {{message.dateRead + 'Z' | timeago}})</span>
                  </div>
                  <img src="https://mdbcdn.b-cdn.net/img/Photos/new-templates/bootstrap-chat/ava4-bg.webp"
                       alt="avatar 1" style="width: 45px; height: 100%;">
                </div>
              </ng-container>

            </div>

          <form [formGroup]="messageForm" enctype="multipart/form-data" (ngSubmit)="createNewMessage()">
            <div class="card-footer text-muted d-flex justify-content-start align-items-center p-3">
              <img src="https://mdbcdn.b-cdn.net/img/Photos/new-templates/bootstrap-chat/ava3-bg.webp"
                   alt="avatar 3" style="width: 40px; height: 100%;">
              <input type="text" class="form-control form-control-lg" id="exampleFormControlInput1"
                     placeholder="Type message" formControlName="content" name="content">
              <a class="ms-1 text-muted" href="#!"><i class="fas fa-paperclip"></i></a>
              <a class="ms-3 text-muted" href="#!"><i class="fas fa-smile"></i></a>
              <button class="btn btn-primary" type="submit">Send</button>
            </div>
          </form>

        </div>
      </div>

    </div>
  </div>

  </div>
</section>
解决方案

1. 修复SignalR数据流推送逻辑

  • 确保messageService.messageThread$基于BehaviorSubject/ReplaySubject实现,且收到SignalR消息时,通过创建新数组触发数据流更新:
    // messageService.ts
    import { BehaviorSubject } from 'rxjs';
    import { Message } from './your-message-model';
    
    private messageThreadSource = new BehaviorSubject<Message[]>([]);
    messageThread$ = this.messageThreadSource.asObservable();
    
    // SignalR消息监听逻辑
    this.hubConnection.on('ReceiveMessage', (newMessage: Message) => {
      const currentMessages = this.messageThreadSource.value;
      // 必须创建新数组,Angular变更检测才能识别变化
      this.messageThreadSource.next([...currentMessages, newMessage]);
    });
    

2. 触发MDB滚动条自动更新

模板中使用了data-mdb-perfect-scrollbar,新消息加入后需手动滚动到底部:

// 组件中添加滚动方法
scrollToBottom() {
  const chatContainer = document.querySelector('.card-body[data-mdb-perfect-scrollbar]');
  if (chatContainer) {
    setTimeout(() => {
      chatContainer.scrollTop = chatContainer.scrollHeight;
    }, 100);
  }
}

// 在收到新消息或发送消息后调用该方法

3. 处理OnPush变更检测(若使用)

如果组件设置了ChangeDetectionStrategy.OnPush,需手动触发变更检测:

import { ChangeDetectorRef } from '@angular/core';

constructor(private cdr: ChangeDetectorRef) {}

// 更新数据流后调用
this.cdr.detectChanges();

4. 优化本地消息更新

发送消息时先本地更新数据,无需等待后端推送,提升体验:

async createNewMessage() {
  if (this.messageForm.valid) {
    const newMessage = {
      ...this.messageForm.value,
      senderUsername: this.currentUser!.userName,
      messageSent: new Date(),
      dateRead: null
    };
    // 本地更新消息列表
    const currentMessages = this.messageService.messageThreadSource.value;
    this.messageService.messageThreadSource.next([...currentMessages, newMessage]);
    // 清空输入框
    this.messageForm.reset();
    // 发送到后端
    await this.hubConnection.invoke('SendMessage', newMessage);
    // 滚动到底部
    this.scrollToBottom();
  }
}

内容的提问来源于stack exchange,提问作者Jean De La Hone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:40:50