Quasar QSelect首次打开未定位至选中选项问题求助
QSelect首次打开未滚动到选中项,二次打开正常的问题排查
我基于Quasar UI构建Vue 3/TypeScript应用,开发带国家下拉框的国际电话输入组件时遇到问题:使用QSelect实现的下拉框,首次打开选项列表时停在顶部,不会自动滚动到当前选中项;但关闭后重新打开,就能正确滚动到选中项——这才是首次打开时的预期行为。
已尝试的无效方案
在handleOnCountryOptionsShow方法中试过以下操作,均未解决问题:
- 调用
reset()、refresh()、updateMenuPosition()方法 - 获取选中项索引后调用
scrollTo(index) - 使用
nextTick()等待渲染完成
问题复现代码
<template> <q-input ref="inputElement" v-model="inputNumber"> <template #prepend> <q-select ref="countrySelectElement" v-model="countrySelected" :options="countryOptions" option-value="id" option-label="name" :virtual-scroll-slice-size="countryOptions?.length" :virtual-scroll-item-size="countryOptionItemHeight" @popup-show="handleOnCountryOptionsShow" > <template #option="scope"> <div> <div class="country-item q-pa-sm cursor-pointer" :class="{ 'country-option-focused': scope.focused }" > {{ scope.opt.name }} </div> <q-resize-observer @resize="hanldeCountryOptionResize" ></q-resize-observer> </div> </template> <template #selected-item="scope"> <div v-if="scope.opt"> {{ scope.opt.name }} </div> </template> </q-select> <q-separator vertical /> </template> </q-input> </template> <script lang="ts" setup> import { nextTick, onMounted, ref } from "vue"; import { QSelect, QInput, QResizeObserver } from "quasar"; const inputElement = ref<QInput | null>(null); const inputNumber = ref<string>(); const countrySelectElement = ref<QSelect | null>(null); const countrySelected = ref<{ id: number; name: string }>(); const countryOptions = ref<{ id: number; name: string }[]>(); const countryOptionItemHeight = ref(0); const generateCountries = () => { const countries: { id: number; name: string }[] = []; for (let i = 1; i <= 250; i++) { countries.push({ id: i, name: `Country ${i}` }); } return countries; }; const hanldeCountryOptionResize = (size: { height: number; width: number }) => { if (!countryOptionItemHeight.value) { countryOptionItemHeight.value = size.height; } }; onMounted(() => { // 生成国家列表 countryOptions.value = generateCountries(); // 初始化选中项 countrySelected.value = countryOptions.value[111]; }); const handleOnCountryOptionsShow = async () => { await nextTick(); const index = countrySelectElement.value?.getOptionIndex(); console.log("index", index); // 能正确打印选中项索引 countrySelectElement.value?.reset(); countrySelectElement.value?.refresh(); countrySelectElement.value?.updateMenuPosition(); if (index) countrySelectElement.value?.scrollTo(index); }; </script> <style> .country-item:hover, .country-option-focused { background-color: #eeeeee; } </style>
问题截图

关键发现
经测试,问题与自定义#option插槽相关——移除该插槽后,QSelect首次打开就能正常滚动到选中项,但我需要保留自定义插槽的样式。
解决方案
1. 修复虚拟滚动高度初始化问题
首次打开时,countryOptionItemHeight可能还未通过resize-observer获取到正确值,导致虚拟滚动无法计算选中项位置。可以提前设置默认高度:
onMounted(() => { countryOptions.value = generateCountries(); countrySelected.value = countryOptions.value[111]; // 提前设置默认高度(根据自定义选项的样式调整,比如q-pa-sm的元素高度约48px) countryOptionItemHeight.value = 48; });
2. 调整滚动触发时机
虚拟列表首次渲染需要更多时间,可通过两次nextTick确保DOM完全渲染后再触发滚动:
const handleOnCountryOptionsShow = async () => { await nextTick(); await nextTick(); // 等待虚拟列表完成渲染 const index = countrySelectElement.value?.getOptionIndex(); if (index !== undefined) { countrySelectElement.value?.scrollTo(index); } };
3. 优化虚拟滚动配置
移除virtual-scroll-slice-size="countryOptions?.length",该配置会强制渲染所有选项,失去虚拟滚动意义,同时可能干扰滚动计算:
<q-select ref="countrySelectElement" v-model="countrySelected" :options="countryOptions" option-value="id" option-label="name" :virtual-scroll-item-size="countryOptionItemHeight" @popup-show="handleOnCountryOptionsShow" >
内容的提问来源于stack exchange,提问作者TinyTiger
相关产品推荐
相关产品推荐

