Javascript 在不使用setTimeout()的情况下滚动到div的底部
我正在使用Firebase制作一个内部实时聊天系统。我拨打此电话是为了获取所有聊天信息的列表:Javascript 在不使用setTimeout()的情况下滚动到div的底部,javascript,angular,firebase,firebase-realtime-database,Javascript,Angular,Firebase,Firebase Realtime Database,我正在使用Firebase制作一个内部实时聊天系统。我拨打此电话是为了获取所有聊天信息的列表: firebase.database().ref('chatrooms/'+this.roomkey+'/chats').on('value', resp => { this.chats = []; this.chats = snapshotToArray(resp); setTimeout(() => { if(this.content._scr
firebase.database().ref('chatrooms/'+this.roomkey+'/chats').on('value', resp => {
this.chats = [];
this.chats = snapshotToArray(resp);
setTimeout(() => {
if(this.content._scroll) { this.content.scrollToBottom(0); }
}, 1000);
});
在我看来,我可以在聊天中循环使用以下HTML:
<ion-content>
<ion-list>
<ion-item *ngFor="let chat of chats" no-lines>
<div class="chat-status" text-center *ngIf="chat.type==='join'||chat.type==='exit';else message">
<span class="chat-date">{{chat.sendDate | date:'short'}}</span>
<span class="chat-content-center">{{chat.message}}</span>
</div>
<ng-template #message>
<div class="chat-message" text-right *ngIf="chat.user === nickname">
<div class="right-bubble">
<span class="msg-name">Me</span>
<span class="msg-date">{{chat.sendDate | date:'short'}}</span>
<p text-wrap>{{chat.message}}</p>
</div>
</div>
<div class="chat-message" text-left *ngIf="chat.user !== nickname">
<div class="left-bubble">
<span class="msg-name">{{chat.user}}</span>
<span class="msg-date">{{chat.sendDate | date:'short'}}</span>
<p text-wrap>{{chat.message}}</p>
</div>
</div>
</ng-template>
</ion-item>
</ion-list>
</ion-content>
目前有30条聊天信息。它们从Firebase加载,然后在一秒钟后,当setTimeout完成时,用户会自动滚动到页面底部,以便查看最新消息。这使得页面加载有点奇怪,一秒钟后跳转到页面底部
是否有任何方法可以将超时替换为可以实现用户最初看到最新消息的目标?可能有一些触发器可以检测到视图中的
聊天
已更改,然后滚动?这似乎比固定的1秒暂停要好?当检测到聊天列表的更改时,您可以滚动到列表的底部:
- 将模板引用变量与
元素关联(例如离子项
)#chatItems
- 使用
获取ViewChildren
元素的ion项
QueryList
- 在
中,订阅ngAfterViewInit
事件QueryList.changes
- 列表更改时滚动至列表底部
...
导出类MyComponent{
@ViewChildren(“聊天项目”)聊天项目:QueryList;
ngAfterViewInit(){
this.scrollContentToBottom();
此.chatItems.changes.subscribe(()=>{
this.scrollContentToBottom();
});
}
scrollContentToBottom(){
如果(this.content._滚动){
this.content.scrollToBottom(0);
}
}
...
}
注意:我使用了
QueryList
,因为我不知道ion项的组件类型。如果您知道它是什么,您可以输入适当的类型。使用“值”事件,您将在该位置收听整个数据集。也许通过使用其他侦听器之一(例如添加的child\u
或更改的child\u
),您可以找到一个更平滑、更友好的解决方案。您好,这是一个很大的帮助,谢谢。如果我现在点击按钮打开我的聊天模式窗口,那么我会立即滚动到聊天模式的底部。如果我随后关闭模式窗口,返回我的应用程序,使用其他手机并发送新消息,请在第一台设备上重新打开模式窗口。。。我没有被向下滚动。我仍然是聊天的焦点。我知道ngAfterViewInit在第二次打开时被触发。订阅是否只检测第一次更改而不检测后续更改?当您第二次打开模式时,新消息是否显示在列表中?如果是,则可能列表已在ngAfterViewInit
中完成,因此不会触发更改
事件。我修改了答案,添加了一个默认的滚动条,以考虑这种可能性。我已经根据您的编辑更新了代码。是的,如果我向下滚动,新消息会出现在聊天中,但仍然没有更改,在模式窗口的第二次(以及随后)打开时,我没有滚动到底部,我仍然在顶部!(感谢您目前的帮助!)不幸的是,我无法在这里调试它。您是否可以使用一些控制台.log
语句检查每次打开模式时执行ngAfterViewInit
,并且触发更改
回调?我不熟悉爱奥尼亚,所以我不知道这个.content.\u scroll
是否总是true
(或者是否需要检查)。这很奇怪。我添加了一大堆console.log,每次都会触发完全相同的事件。目前,我在scrollContentToBottom函数中添加了一个100ms的setTimeout,这使得每次打开的聊天模式窗口都能适当地滚动。setTimeout(()=>{this.content.scrolltobttom(0);},100);
ion-content {
height: 100%;
overflow: hidden;
.item-md, .item-ios {
background: none;
}
}
<ion-content>
<ion-list>
<ion-item #chatItems *ngFor="let chat of chats" no-lines>
...
</ion-item>
</ion-list>
</ion-content>
export class MyComponent {
@ViewChildren("chatItems") chatItems: QueryList<any>;
ngAfterViewInit() {
this.scrollContentToBottom();
this.chatItems.changes.subscribe(() => {
this.scrollContentToBottom();
});
}
scrollContentToBottom() {
if(this.content._scroll) {
this.content.scrollToBottom(0);
}
}
...
}