英文:
Sending/receiving a new message takes me to top of the screen on chat app
问题
这是您提供的代码部分的翻译:
我正在尝试使用Angular Firestore和Firebase在应用程序中实现聊天功能,我使用可观察对象获取所有消息。获取所有消息没有问题,但一旦我发送一条新消息或在聊天中接收一条消息,屏幕就会自动滚动到顶部并锁定在那里。
这是我聊天服务中获取消息的代码:
getMessages(id){
return this.afs.collectionchats/${id}/messages
, ref => ref.orderBy('createdAt','asc').limitToLast(20)).valueChanges()
}
这是 TypeScript 部分:
getMessages(){
this.user$ = this.cs.getMessages(this.chatID)
}
并且在 HTML 中使用异步管道来显示:
<ion-row class="ion-align-items-center" *ngFor="let message of user$ | async;">
....
[这是发送消息时应用程序的外观](https://i.stack.imgur.com/a658I.gif)
我创建了一个函数,用于在进入视图或发送消息时滚动到底部:
```javascript
sendChatMessage(msg){
return this.afs.collection(`chats/${this.chatID}/messages`).add({
msg: msg,
from: this.uid,
fromName: this.myName,
createdAt: firebase.firestore.FieldValue.serverTimestamp()
})
}
submit() {
this.sendChatMessage(this.newMsg).then(() => {
this.newMsg = '';
this.scrollToBottom(100, 100);
});
}
scrollToBottom(delay, time){
setTimeout(() => {
this.myContent.scrollToBottom(time);
}, delay);
}
我希望在提交消息时,视图保持在用户提交消息时的位置,或者仅滚动到最新消息而不先向上滚动。有什么办法可以修复这个问题吗?
这会使接收新消息变得混乱,因为如果您在聊天中滚动并收到新消息,用户将被自动传送到屏幕顶部。
我已经尝试更改从Firebase获取消息的方式(删除20条限制),更改为 valueChanges 等。我不确定是什么导致了这种行为。
我还尝试锁定视图,但它仅在一条消息上起作用,然后返回到先前的行为。
<details>
<summary>英文:</summary>
I'm trying to implement a chat functionality using Angular Firestore and Firebase in an app and I get all the messages using an observable. Getting all the messages works fine but as soon as I send a new message or receive a message in the chat the screen goes all the way up and gets locked there.
This is the code in my chat service to get the messages:
getMessages(id){
return this.afs.collection<any>(chats/${id}/messages
, ref => ref.orderBy('createdAt','asc').limitToLast(20)).valueChanges()
}
This is the TS:
` getMessages(){this.user$ = this.cs.getMessages(this.chatID)}`
And it's displayed in the HTML using an async pipe:
<ion-row class="ion-align-items-center" *ngFor="let message of user$ | async;">
....
</ion-row>
[This is how it looks in the app when sending a message](https://i.stack.imgur.com/a658I.gif)
I made a function to scroll down the view when entering the view or sending a message:
sendChatMessage(msg){
return this.afs.collection(chats/${this.chatID}/messages
).add({
msg: msg,
from: this.uid,
fromName: this.myName,
createdAt: firebase.firestore.FieldValue.serverTimestamp()
})
}
submit() {
this.sendChatMessage(this.newMsg).then(()=>{
this.newMsg = '';
this.scrollToBottom(100,100)
});
}
scrollToBottom(delay, time){
setTimeout(() => {
this.myContent.scrollToBottom(time);
}, delay);
}
[This is what it looks like with the scrollToBottom function](https://i.stack.imgur.com/2gjbU.gif)
I would like it so that the view is stuck on where the user was when submitting the message or that it only scrolls down to latest message without scrolling up first. Any ideas how to fix this?
[This is also what it looks like when receiving message from others(no scrolldown)](https://i.stack.imgur.com/ONl0O.gif)
This makes the whole receiving of new messages messy because if you are scrolling through the chat and receive a new one the user will be transported automatically to the top of the screen.
I've tried changing the way I get the message from Firebase ( removing limit of 20), changing from valuechanges etc. I'm not sure what it is that's causing the behaviour.
I've also tried locking the view but it only works for one message then it goes back to previous behaviour.
</details>
# 答案1
**得分**: 0
你的CSS怎么样?看起来你的CSS中有一些激活滚动到顶部的内容。请尝试像这样更改你消息容器的CSS:
```css
.messages-container {
width: 100%;
display: flex;
min-height: 100%;
position: relative;
overflow: hidden;
margin: 0 auto;
}
英文:
How is your CSS? It seems me you have some CSS activating the scroll to up. Please, try to change your CSS from the messages container like this:
.messages-container {
width: 100%;
display: flex;
min-height: 100%;
position: relative;
overflow: hidden;
margin: 0 auto;
}
答案2
得分: 0
我从Reddit上的一个用户那里得到了一些帮助:
我认为可能发生的情况是,当发送新消息时,user$的值是一个新的数组引用,这会导致列表滚动到顶部,而所有的消息项都被重新创建。为了避免这种情况,你可以定义一个 TrackByFunction,这样Angular只会创建新的项目。
我在我的代码中添加了一个TrackByFunction:
<ion-row class="ion-align-items-center" *ngFor="let message of user$ | async; trackBy: trackByFn">
....
</ion-row>
trackByFn(message) {
return message.id;
}
这解决了我在这个项目中的问题。
英文:
I got some help from a user on reddit:
> I think what might be happening is that when a new message is sent, the value of user$ is a new array reference -- which causes the list to scroll up while all of the message items are recreated. To avoid this you can define a TrackByFunction so that Angular only creates items that are new.
I added a TrackByFunction to my code:
<ion-row class="ion-align-items-center" *ngFor="let message of user$ | async; trackBy: trackByFn">
....
</ion-row>
trackByFn(message) {
return message.id;
This solved my issue on this project.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论