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

Angular+SignalR群聊消息无法实时更新,需聚焦输入框才显示

群组聊天应用实时更新问题

我开发了一个简单的群组聊天应用,当用户发送消息或加入群组时,通知本应实时推送给群组内所有用户。

界面展示

  • 加入群组界面:
    加入群组界面
  • 发送消息界面:
    发送消息界面
  • 需聚焦输入框才显示消息的状态:
    需聚焦输入框才显示消息

但目前存在问题:显示消息的div仅在当前操作的用户窗口更新,其他打开的窗口不会自动刷新消息,只有当用户聚焦输入框时,该窗口的消息div才会更新内容。


Angular 代码

app.component.html

<div *ngIf="!joined">
  <strong>Create a group</strong><br><br>
  <div>
    <label>Group name:</label>
    <input type="text" name="groupName" [(ngModel)]="groupName" />
  </div><br>
  <div>
    <label>User name:</label>
    <input type="text" name="userName" [(ngModel)]="userName" />
  </div><br>
  <button type="button" (click)="join()">Enter</button>
</div>

<div *ngIf="joined">
  <div id="chat">
    <div *ngFor="let message of conversation">
      <span>{{message.userName}} : {{message.message}}</span>
    </div>
  </div>
  <input type="text" [(ngModel)]="messageToSend" name="messageToSend" />
  <button (click)="sendMessage()">Send</button>
  <button (click)="leave()">Leave</button>
</div>

app.component.ts

import { Component, OnInit } from '@angular/core';
import { HubConnection, HubConnectionBuilder } from '@microsoft/signalr';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit{

  public userName = '';
  public groupName = 'demo';
  public messageToSend = '';
  public joined = false;
  public conversation: NewMessage[] = [{
    message: 'Welcome',
    userName: 'Chat'
  }];

  private connection: HubConnection;

  constructor() {
    this.connection = new HubConnectionBuilder()
      .withUrl('https://localhost:7133/chat')
      .build();

    this.connection.on("NewUser", message => this.newUser(message));
    this.connection.on("NewMessage", message => this.newMessage(message));
    this.connection.on("LeftUser", message => this.leftUser(message));
  }

  ngOnInit(): void {
    this.connection.start()
      .then(_ => {
        console.log('Connection Started');
      }).catch(error => {
        return console.error(error);
      });
  }

  public join() {
    this.connection.invoke('JoinGroup', this.groupName, this.userName)
      .then(_ => {
        this.joined = true;
      });
  }

  public sendMessage() {
    const newMessage: NewMessage = {
      message: this.messageToSend,
      userName: this.userName,
      groupName: this.groupName
    };

    this.connection.invoke('SendMessage', newMessage)
      .then(_=> this.messageToSend = '');
  }

  public leave() {
    this.connection.invoke('LeaveGroup', this.groupName, this.userName)
      .then(_ => this.joined = false);
  }

  private newUser(message: string) {
    console.log(message);
    this.conversation.push({
      userName: 'Chat',
      message: message
    });
  }

  private newMessage(message: NewMessage) {
    console.log(message);
    this.conversation.push(message);
  }
  private leftUser(message: string) {
    console.log(message);
    this.conversation.push({
      userName: 'Sistema',
      message: message
    });
  }
}
export class NewMessage {
  userName: string;
  message: string;
  groupName?: string;
}

API C# 代码

Hub

namespace ApiChat.Hubs
{
    public class ChatHub:Hub
    {
        public async Task JoinGroup(string groupName, string userName)
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
            await Clients.Group(groupName).SendAsync("NewUser", $"{userName} joined the group");
        }
        public async Task LeaveGroup(string groupName, string userName)
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
            await Clients.Group(groupName).SendAsync("LeftUser", $"{userName} left the group");
        }
        public async Task SendMessage(NewMessage message)
        {
            await Clients.Group(message.GroupName).SendAsync("NewMessage", message);
        }
    }
    public record NewMessage(string UserName, string Message, string GroupName);
}

Program.cs

builder.Services.AddSignalR();
app.UseCors(builder =>
{
    builder
        .AllowAnyHeader()
        .AllowAnyMethod()
        .AllowCredentials()
        .WithOrigins("http://localhost:4200");
});
app.MapHub<ChatHub>("/chat");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:16:22