使用ASP.NET Core,Angular 5和SignalR开发应用程序时,我遇到了一个问题。
作为测试,我根据此示例创建了一个简单的聊天应用:https://codingblast.com/asp-net-core-signalr-chat-angular/
但是,当我从
this.hubConnection.on('sendToAll', (nickname: string, message: string) => { this.messages.push(new Message(nickname, message)); });
// or this line
this.hubConnection.on('sendToAll', (nickname: string, message: string) => { this.addMessage(nickname, message); });
到
this.hubConnection.on('sendToAll', this.addMessage);
DOM未更新。
我已经逐步完成了,我设法弄清楚当回调到来时,它实际上是组件的另一个实例......所以每个字段都是未定义的。
以下是完整的组件:
chat.component.html
<section class="card">
<div class="card-body" *ngIf="messages !== undefined">
<div *ngFor="let msg of messages">
<strong>{{msg.nickname}}</strong>: {{msg.message}}
</div>
</div>
<div class="card-footer">
<form class="form-inline" (ngSubmit)="sendMessage()" #chatForm="ngForm">
<div class="form-group">
<label class="sr-only" for="nickname">Nickname</label>
<input type="text" id="nickname" name="nickname" placeholder="Nickname" [(ngModel)]="nickname" required />
</div>
<div class="form-group">
<label class="sr-only" for="message">Message</label>
<input type="text" id="message" name="message" placeholder="Your message" [(ngModel)]="message" required />
</div>
<button class="btn btn-sm" type="submit" id="sendmessage" [disabled]="!chatForm.valid">Send</button>
</form>
</div>
</section>
chat.component.ts
import { Component, OnInit } from '@angular/core';
import { HubConnection } from '@aspnet/signalr';
import { Message } from '../../models/message';
@Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.css']
})
export class ChatComponent implements OnInit {
private hubConnection: HubConnection;
public nickname: string;
public message: string;
public messages: Message[];
constructor() {
this.messages = [];
}
ngOnInit() {
this.hubConnection = new HubConnection('http://localhost:55233/chat');
this.hubConnection.start().then(() => console.log('connection started')).catch(err => console.error(err));
this.hubConnection.on('sendToAll', this.addMessage);
}
private addMessage(nickname: string, message: string): void {
// this line is useful to avoid undefined error
// due to the callback pointing to another instance of this component...
if (this.messages === undefined) {
this.messages = [];
}
this.messages.push(new Message(nickname, message));
}
public sendMessage(): void {
this.hubConnection
.invoke('sendToAll', this.nickname, this.message)
.catch(err => console.error(err));
}
}
这是我尝试过的:
如何在此上下文中使用此行this.hubConnection.on('sendToAll', this.addMessage);
?
谢谢你的帮助。
编辑:
感谢Supamiu,这是解决方案:
this.hubConnection.on('sendToAll', this.addMessage.bind(this));
答案 0 :(得分:2)
this.hubConnection.on('sendToAll', this.addMessage);
相当于
this.hubConnection.on('sendToAll', function(x) { this.addMessage(x); });
在javascript中,你必须在编写函数时使用闭包,或者使用胖箭头。这会给出
const that = this;
this.hubConnection.on('sendToAll', function(x) { that.addMessage(x); });
// or
this.hubConnection.on('sendToAll', x => { this.addMessage(x); });
答案 1 :(得分:1)
Javascript提供了一种将上下文注入方法调用的工具:bind。
您应该将this.addMessage
更改为this.addMessage.bind(this)
。
请记住,还有其他解决方案,例如解释过的三个解决方案,另一个解决方案是更改addMessage
箭头函数,因为箭头函数保持this
上下文:
private addMessage = (nickname: string, message: string) => {
// this line is useful to avoid undefined error
// due to the callback pointing to another instance of this component...
if (this.messages === undefined) {
this.messages = [];
}
this.messages.push(new Message(nickname, message));
}
通过这样做,您仍然可以使用this.addMessage
而无需绑定this
上下文。