我一直在推迟解决我已经有一段时间的错误了。我有下面的聊天窗口:
显示消息的窗口是一个单独的组件(chat-window.component.ts)。我想使用ngOnChanges滚动到底部。
当我们从父组件接收到带有消息的会话(通过异步请求从服务器接收到该消息)时,我们想滚动到window元素的底部。我们通过在ngOnChanges生命周期挂钩中调用该类的this.scrollToBottom()
方法来实现。
This.scrollToBottom确实会被调用,但不会滚动到该元素的底部。有人可以看到原因吗?
聊天窗口.component.ts:在ngOnchanges中,我们在调用this.scrollToBottom()
之前会做一些同步处理export class ChatboxWindowComponent implements OnChanges, OnInit, AfterViewChecked {
@Input('conversation') conversation;
@ViewChild('window') window;
constructor() { }
ngOnChanges() {
// If the date separators have already been added once, we avoid doing it a second time
const existingDateObj = this.conversation.messages.findIndex((item, i) => item.dateObj);
if (existingDateObj === -1) {
this.conversation.messages.forEach( (item, index, array) => {
if (index !== 0) {
const date1 = new Date(array[index - 1].date);
const date2 = new Date(item.date);
if (date2.getDate() !== date1.getDate() || date2.getMonth() !== date1.getMonth()) {
this.conversation.messages.splice(index, 0, {date: date2, dateObj: true});
console.log(this.conversation.messages.length);
}
}
});
}
this.scrollToBottom();
}
ngOnInit() {
}
ngAfterViewChecked() {
}
isItMyMsg(msg) {
return msg.from._id === this.conversation.otherUser.userId;
}
scrollToBottom() {
try {
console.log('scrollToBottom called');
this.window.nativeElement.top = this.window.nativeElement.scrollHeight;
} catch (err) {}
}
}
聊天窗口.component.html
<div #window class="window">
<ng-container *ngFor="let message of conversation.messages">
<div class="date-container" *ngIf="!message.msg; else windowMsg">
<p class="date">{{message.date | amDateFormat:'LL'}}</p>
</div>
<ng-template #windowMsg>
<p
class="window__message"
[ngClass]="{
'window__message--left': isItMyMsg(message),
'window__message--right': !isItMyMsg(message)
}"
>
{{message.msg}}
</p>
</ng-template>
</ng-container>
</div>
答案 0 :(得分:4)
滚动不起作用,因为调用scrollToBottom
时尚未呈现消息列表。为了在消息显示后立即滚动,请在消息容器上设置template reference variable(例如#messageContainer
)
<ng-container #messageContainer *ngFor="let message of conversation.messages">
...
</ng-container>
然后,在代码中,您可以使用ViewChildren
访问这些元素,并在触发QueryList.changes
事件时滚动窗口:
@ViewChildren("messageContainer") messageContainers: QueryList<ElementRef>;
ngAfterViewInit() {
this.scrollToBottom(); // For messsages already present
this.messageContainers.changes.subscribe((list: QueryList<ElementRef>) => {
this.scrollToBottom(); // For messages added later
});
}
答案 1 :(得分:0)
您可以将以下代码添加到您的 HTML 元素中。
#window [scrollTop]="window.scrollHeight" *ngIf="messages.length > 0"
根据您的代码示例的完整代码如下,
<div #window [scrollTop]="window.scrollHeight" *ngIf="messages.length > 0" class="window">
<ng-container *ngFor="let message of conversation.messages">
<div class="date-container" *ngIf="!message.msg; else windowMsg">
<p class="date">{{message.date | amDateFormat:'LL'}}</p>
</div>
<ng-template #windowMsg>
<p
class="window__message"
[ngClass]="{
'window__message--left': isItMyMsg(message),
'window__message--right': !isItMyMsg(message)
}"
>
{{message.msg}}
</p>
</ng-template>
</ng-container>
</div>
这对我有用。 (目前,我使用的是 Angular 11)??