Vue 3 Composition Api中动态Ref未正确绑定至响应式数组问题
解决Vue 3 Composition API中动态Ref无法正确收集元素的问题
你的问题主要出在两个核心点:模板内联ref回调的作用域偏差,以及缺少组件更新时的ref数组重置逻辑。咱们一步步拆解解决:
问题原因分析
- 内联函数的作用域问题:你在模板里直接写的箭头函数
:ref="(el) => { if (el) { divs.push(el) } }",看似能访问到divs,但实际上这个函数里的divs并没有正确绑定到setup中定义的响应式ref数组。Vue会把这个内联函数作为标识存到$refs里,这就是为什么你在$refs里能看到元素集合,但自己定义的divs始终为空。 - 无更新重置逻辑:就算回调能正常执行,当
storyList变化时,旧的DOM元素会被卸载,但你的divs数组不会自动清空,最终会积累大量无效的旧元素引用,不符合预期。
正确实现方案
参考Vue官方示例的思路,把ref回调移到setup中定义,同时添加更新钩子来维护数组的纯净性,代码如下:
<template> <section v-for="(item, i) of storyList" :ref="setDivRef" :key="item.id" /> </template> <script lang="ts"> import { defineComponent, ref, onBeforeUpdate, onUpdated } from 'vue'; // 假设StoryList是你的自定义类型 type StoryList = { id: string; /* 其他字段 */ }[]; export default defineComponent({ props: { storyList: { type: Array as () => StoryList, required: true, }, }, setup() { // 定义存储元素ref的响应式数组 const divs = ref<HTMLElement[]>([]); // 定义ref回调函数,直接访问setup作用域内的divs const setDivRef = (el: HTMLElement | null) => { if (el) { divs.value.push(el); } }; // 组件更新前清空数组,避免旧元素残留 onBeforeUpdate(() => { divs.value = []; }); // 可选:更新完成后验证收集结果 onUpdated(() => { console.log('已收集的元素Ref:', divs.value); }); return { setDivRef, divs }; }, }); </script>
关键细节说明
- 回调函数移至setup:这样能确保回调直接绑定
setup作用域内的divsref,元素能正确被收集到响应式数组中,同时Vue能稳定识别这个回调,不会把它作为$refs的标识。 - onBeforeUpdate重置数组:每次组件更新(比如
storyList变化)前清空数组,保证新的元素Ref会被重新收集,避免新旧元素混合。 - 给v-for添加key:这不是Ref收集的必须项,但唯一的
key能帮助Vue更高效地更新DOM,减少不必要的元素销毁重建,让Ref收集更稳定。
修改后,你就能从divs这个响应式数组中正确获取所有<section>元素的Ref,无需依赖Vue 3不推荐使用的$refs。
内容的提问来源于stack exchange,提问作者zero2579
相关产品推荐
相关产品推荐

