
我写了一个更丝滑的上滑加载更多消息列表代码:
点击查看完整源码
<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> 网友回复
如何破解绕开seedance2.0真人照片生成视频 限制?
python有哪些算法可以将视频中的每个帧图片去除指定区域水印合成新的视频?
iphone的激光雷达数据能否实时传输到three三维空间中?
豆包sora等ai视频生成大模型生成的视频水印如何去除?
python如何实现在电脑上拨号打电话给手机?
具身机器人与人形机器人区别?
nodejs如何将一个完整的js代码文件切割成不同的部分混淆后动态加载进入html运行?
为啥windows.onerror捕获js错误是这样的{"message":"Script error.","source":"","lineno":0,"colno":0,"stack":null,
2026年ai将全面接管编程?
WebMCP是干啥的?


