Vue3组合式API:获取激活元素高度失败,如何传递高度至点击元素?
问题解决方法
核心问题
你用单个ref绑定循环里的多个DOM元素,这会导致contentRefs最终只指向最后一个渲染的元素,根本拿不到当前点击元素的高度;同时你也没有专门的变量存储上一个激活元素的高度,无法传递给下一个被点击的元素。
修正后的代码
<script lang="ts" setup> import { ref, reactive, nextTick } from "vue"; defineProps<{ content: Array<{ title: string; content: string }>; }>(); // 改用数组Ref存储所有内容区域的DOM元素 const contentRefs = ref<HTMLDivElement[]>([]); const isToggled = reactive<{ value: number | null }>({ value: null }); // 存储上一个激活元素的高度 const savedHeight = ref(0); const handleClick = async (index: number) => { // 如果之前有激活的元素,先保存它的高度 if (isToggled.value !== null && isToggled.value !== index) { const prevElement = contentRefs.value[isToggled.value]; if (prevElement) { await nextTick(); // 等待DOM更新完成,确保获取的高度准确 savedHeight.value = prevElement.scrollHeight; } } // 切换当前激活项的状态 isToggled.value = isToggled.value === index ? null : index; }; </script> <template> <div v-for="(item, index) in content" class="accordion" :class="{ open: isToggled.value === index }" :key="index" > <div @click="() => handleClick(index)">{{ item.title }}</div> <div :ref="el => el && contentRefs.push(el)" :style="{ minHeight: isToggled.value === index ? `${savedHeight.value || contentRefs.value[index]?.scrollHeight || 0}px` : '0' }" > {{ item.content }} </div> </div> </template>
关键调整说明
- 数组Ref替代单个Ref:循环中每个内容区域的DOM会被收集到
contentRefs数组里,通过索引可以精准获取对应元素的DOM,解决了单个Ref覆盖的问题。 - 保存前序元素高度:点击新元素时,先获取上一个激活元素的
scrollHeight并存储,nextTick确保DOM渲染完成,避免获取到不准确的高度值。 - 高度应用逻辑:当前元素激活时,优先使用保存的前序元素高度;如果是第一次激活或无保存高度,则使用自身的
scrollHeight。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

