You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:55:55