
我写了一个更丝滑的上滑加载更多消息列表代码:
点击查看完整源码
<template>
<view class="container">
<scroll-view
class="scroll-view"
scroll-y
@scrolltoupper="onScrollToUpper"
:scroll-top="scrollTop"
:scroll-with-animation="false"
:refresher-enabled="false"
upper-threshold="150"
style="height: 100vh;"
>
<view class="loading" v-if="isLoading">加载中...</view>
<view
v-for="(message, index) in messages"
:key="message.id"
class="message-item"
>
{{ message.content }}
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
messages: [],
scrollTop: 0,
isLoading: false,
messageId: 0 // 用于生成唯一ID
}
},
mounted() {
this.loadInitialMessages()
},
methods: {
async loadInitialMessages() {
const initialMessages = await this.fetchMessages(20)
this.messages = initialMessages
this.$nextTick(() => {
this.scrollToBottom()
})
},
scrollToBottom() {
// 延迟执行以确保DOM已更新
setTimeout(() => {
const query = uni.createSelectorQuery().in(this)
query.select('.scroll-view').boundingClientRect(data => {
this.scrollTop = data.height * 2
}).exec()
}, 100)
},
async onScrollToUpper() {
if (this.isLoading) return
// 获取当前滚动位置和内容高度
const query = uni.createSelectorQuery().in(this)
query.select('.scroll-view').boundingClientRect(async rect => {
const oldHeight = rect.height
const oldScrollTop = this.scrollTop
this.isLoading = true
console.log("加载更多")
const newMessages = await this.fetchMessages(10)
// 将新消息添加到顶部
this.messages = [...newMessages, ...this.messages]
// 等待DOM更新
this.$nextTick(() => {
query.select('.scroll-view').boundingClientRect(newRect => {
const newHeight = newRect.height
const heightDiff = newHeight - oldHeight
// 调整滚动位置,保持视觉位置不变
this.scrollTop = oldScrollTop + heightDiff
this.isLoading = false
}).exec()
})
}).exec()
},
async fetchMessages(count) {
// 模拟API请求
return new Promise(resolve => {
setTimeout(() => {
const messages = Array.from({ length: count }, () => ({
id: this.messageId++,
content: `历史消息 ${this.messageId}`
}))
resolve(messages)
}, 1000)
})
}
}
}
</script>
<style>
.container {
height: 100vh;
}
.scroll-view {
padding: 20px;
box-sizing: border-box;
}
.message-item {
padding: 10px;
margin: 10px 0;
background: #f5f5f5;
border-radius: 5px;
min-height: 40px;
}
.loading {
text-align: center;
padding: 10px;
color: #999;
}
</style> 网友回复


