Quasar Q-Select无限滚动问题:鼠标滚动参数未更新及触底加载方案问询
在Quasar Q-Select中实现无限滚动的解决方案
利用virtual-scroll事件实现(推荐)
你遇到的鼠标滚动时index参数不更新的问题是正常的——这个参数主要对应键盘导航时的高亮项索引。但我们可以用事件返回的to参数(当前可见区域的最后一项索引)来判断是否接近底部,触发加载。
具体实现要点:
- 设定一个阈值(比如5),当当前可见最后一项索引
to与总数据量的差值小于等于这个阈值时,发起新的数据请求。 - 加一个
isLoading状态锁,避免重复触发请求。
示例代码:
<template> <q-select v-model="selected" :options="options" virtual-scroll @virtual-scroll="handleVirtualScroll" :loading="isLoading" placeholder="选择选项" /> </template> <script setup> import { ref } from 'vue' const selected = ref(null) const options = ref([]) const isLoading = ref(false) const totalItems = ref(0) // 后端返回的总数据条数 const page = ref(1) const pageSize = ref(20) // 替换为你的实际接口请求 const loadMoreData = async () => { isLoading.value = true // 用setTimeout模拟异步请求 await new Promise(resolve => setTimeout(resolve, 1000)) const newData = Array.from({ length: pageSize.value }, (_, i) => ({ label: `选项 ${(page.value - 1) * pageSize.value + i + 1}`, value: (page.value - 1) * pageSize.value + i + 1 })) options.value = [...options.value, ...newData] totalItems.value = 100 // 假设总共有100条数据 page.value += 1 isLoading.value = false } const handleVirtualScroll = (scrollData) => { // 当可见最后一项距离总数据量小于等于5时,触发加载 if (!isLoading.value && totalItems.value - scrollData.to <= 5) { loadMoreData() } } // 初始化加载第一页 loadMoreData() </script>
直接监听下拉菜单的滚动事件(备选方案)
如果virtual-scroll的方式不符合你的需求,也可以直接获取Q-Select下拉菜单的DOM元素,监听其原生scroll事件来判断滚动位置:
<template> <q-select ref="selectRef" v-model="selected" :options="options" :loading="isLoading" placeholder="选择选项" /> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue' const selected = ref(null) const options = ref([]) const isLoading = ref(false) const selectRef = ref(null) const totalItems = ref(0) const page = ref(1) const pageSize = ref(20) const loadMoreData = async () => { isLoading.value = true await new Promise(resolve => setTimeout(resolve, 1000)) const newData = Array.from({ length: pageSize.value }, (_, i) => ({ label: `选项 ${(page.value - 1) * pageSize.value + i + 1}`, value: (page.value - 1) * pageSize.value + i + 1 })) options.value = [...options.value, ...newData] totalItems.value = 100 page.value += 1 isLoading.value = false } const handleScroll = (e) => { const menuEl = e.target // 滚动条距离底部小于100px时触发加载 if (!isLoading.value && (menuEl.scrollHeight - menuEl.scrollTop - menuEl.clientHeight) < 100) { loadMoreData() } } onMounted(() => { const menuEl = selectRef.value?.$el.querySelector('.q-select__menu') if (menuEl) { menuEl.addEventListener('scroll', handleScroll) } }) onUnmounted(() => { const menuEl = selectRef.value?.$el.querySelector('.q-select__menu') if (menuEl) { menuEl.removeEventListener('scroll', handleScroll) } }) loadMoreData() </script>
内容的提问来源于stack exchange,提问作者Yashar Vasegh
相关产品推荐
相关产品推荐

