vue 滚动触底加载下一页

文章介绍了如何在Vue应用中使用滚动事件(handleScroll)检测滚动条滚动到页面底部,并基于此动态加载更多数据,如房间列表,实现分页效果。
<div ref="scrollbar" style="height:500px" @scroll="handleScroll"></div>
data() {
	return {
		scrollTop: 0, //列表分页加载定位
	}
},
mounted() {
    this.handleScroll()
}

handleScroll() {
	if (!this.$refs.scrollbar || this.$refs.scrollbar.scrollTop === 0) return
    let scrollTop = this.$refs.scrollbar.scrollTop
    let scrollHeight = this.$refs.scrollbar.scrollHeight
    let clientHeight = this.$refs.scrollbar.clientHeight
    if ((scrollHeight - clientHeight) <= scrollTop) {
        //滚动条滚到底部
        if (this.pagination.currentPage < this.pagination.totalPages) {
          this.scrollTop = scrollTop
          this.pagination.currentPage++
          this.getRoomList().then(() => {
            this.$refs.scrollbar.scrollTop = this.scrollTop
          })
        }
    }
},
<think>我们正在使用Vue 3来实现一个左侧会话记录列表,需要具备两个主要功能: 1. 触底请求下一页(无限滚动2. 删除功能 根据引用[1],我们可以知道在微信小程序中下拉刷新和上拉加载的事件处理,但这里我们是在Vue 3中实现,所以我们需要使用Vue 3的方式来实现无限滚动触底加载一页)。另外,引用[2]提到了在Vue中修改数据后立即获取DOM需要使用$nextTick,但在这里我们主要关注数据驱动的视图更新。 另外,引用[4]提到了vuex和localStorage的相关内容,我们可以考虑将会话记录存储在vuex中,同时为了持久化,可能需要结合localStorage(但根据需求,暂时只需要实现列表和删除,持久化不是重点)。 设计思路: 1. 使用一个数组来存储会话记录(chatSessions),每个会话记录是一个对象。 2. 使用一个变量(currentPage)来记录当前页码,每次触底加载一页时,页码加1,并请求数据(这里我们假设有一个获取会话记录分页的API)。 3. 使用一个变量(hasMore)来标记是否还有更多数据,如果没有,则不再请求。 4. 监听列表容器的滚动事件,当滚动到底部时,加载一页。 5. 实现删除功能,删除某条会话记录。 由于是在Vue 3中,我们将使用Composition API。 步骤: 1. 创建组件,并设置一个容器用于显示会话列表。 2. 在容器上监听滚动事件,判断是否触底。 3. 实现加载数据的方法(包括初始加载加载更多)。 4. 实现删除方法,从列表中移除对应的会话记录。 注意:在删除时,由于是左侧列表,删除后可能需要更新列表,并重新计算滚动位置等,但通常Vue的响应式系统会自动更新视图。 具体代码实现如下: 首先,我们创建一个组件(ChatSessionList.vue): </think>基于您的需求,我将提供使用 Vue 3 实现左侧会话记录列表(支持触底加载一页和删除功能)的完整方案: ### 核心实现方案 ```vue <template> <div class="session-container"> <div class="session-list" @scroll="handleScroll" ref="scrollContainer" > <div v-for="session in sessions" :key="session.id" class="session-item" > <div class="session-content">{{ session.content }}</div> <button @click="deleteSession(session.id)">删除</button> </div> <div v-if="loading" class="loading">加载...</div> <div v-if="!hasMore" class="no-more">没有更多数据</div> </div> </div> </template> <script setup> import { ref, onMounted } from 'vue' // 响应式数据 const sessions = ref([]) // 会话列表 const currentPage = ref(1) // 当前页码 const loading = ref(false) // 加载状态 const hasMore = ref(true) // 是否有更多数据 const scrollContainer = ref(null) // 滚动容器引用 // 初始化加载数据 onMounted(() => { loadSessions() }) // 模拟API请求 const fetchSessions = async (page) => { return new Promise(resolve => { setTimeout(() => { // 模拟返回10条数据(实际应替换为真实API) const data = Array.from({ length: 10 }, (_, i) => ({ id: `${page}-${i}`, content: `会话记录 ${page}-${i}` })) resolve(data) }, 800) }) } // 加载会话记录 const loadSessions = async () => { if (loading.value || !hasMore.value) return loading.value = true try { const newSessions = await fetchSessions(currentPage.value) if (newSessions.length === 0) { hasMore.value = false } else { sessions.value = [...sessions.value, ...newSessions] currentPage.value++ } } catch (error) { console.error('加载失败:', error) } finally { loading.value = false } } // 触底检测 const handleScroll = () => { const container = scrollContainer.value if (!container) return // 触底判断公式 const isBottom = container.scrollHeight - container.scrollTop <= container.clientHeight + 50 if (isBottom && !loading.value) { loadSessions() } } // 删除会话 const deleteSession = (id) => { sessions.value = sessions.value.filter(session => session.id !== id) // 重要:更新DOM后操作需使用nextTick(参考引用[2]) nextTick(() => { console.log('DOM已更新') // 此处可添加删除后的额外逻辑 }) } </script> <style scoped> .session-container { width: 300px; height: 100vh; border-right: 1px solid #eee; } .session-list { height: 100%; overflow-y: auto; padding: 10px; } .session-item { padding: 12px; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; align-items: center; } .loading, .no-more { text-align: center; padding: 10px; color: #888; } </style> ``` ### 关键实现说明 1. **触底加载机制**: - 使用 `@scroll` 监听滚动事件 - 通过 `scrollHeight - scrollTop <= clientHeight + threshold` 公式检测触底 - 避免重复请求的锁机制 `loading` 2. **数据加载逻辑**: - 分页加载模式 (`currentPage`) - 数据合并: `sessions.value = [...sessions.value, ...newSessions]` - 终止条件检测 (`hasMore`) 3. **删除功能**: - 使用 `filter` 创建新数组实现响应式删除 - 删除后自动更新视图(Vue 响应式特性) - 需要 DOM 更新后操作时使用 `nextTick`(参考引用[2]) 4. **性能优化**: - 滚动事件使用防抖(未在代码展示,建议添加) - 避免不必要的 DOM 操作 - 虚拟滚动建议(超长列表时) ### 相关技术点参考 1. **滚动容器处理**:小程序中使用 `page.json` 启用下拉刷新(引用[1]),但 Vue 中需自行实现滚动容器 2. **DOM 更新时机**:数据修改后获取 DOM 需用 `nextTick`(引用[2]) 3. **状态管理**:如需要跨组件共享会话状态,建议使用 Pinia(Vuex 升级版) 4. **持久化存储**:结合 `localStorage` 时注意字符串转换(引用[4])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值