在Vue中,特别是Vue 3,如果你需要基于主键动态地访问通过v-for循环创建的元素的引用,你可以将ref绑定一个方法用于设置dom的引用达到目的
示例代码
vue
<template>
<div>
<ul>
<li v-for="(item, index) in items" :key="item.id">
<input type="text" :ref="setInputRef(index)" v-model="item.value" />
</li>
</ul>
<button @click="focusInput(0)">Focus First Input</button>
<button @click="focusInput(1)">Focus Second Input</button>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, watchEffect } from 'vue';
// 数据数组
const items = reactive([
{ id: 1, value: 'Item 1' },
{ id: 2, value: 'Item 2' },
]);
// 动态引用集合
const inputRefs = reactive([]);
// 设置输入框的引用
const setInputRef = (index) => (el) => {
if (el) {
inputRefs[index] = el;
}
};
// 聚焦指定索引的输入框
const focusInput = (index) => {
if (inputRefs[index]) {
inputRefs[index].focus();
} else {
console.warn(`Input at index ${index} not found.`);
}
};
// 确保引用数组与items同步
watchEffect(() => {
// 重置引用数组的长度,以匹配items的长度
inputRefs.length = items.length;
});
</script>
解释
- 使用
reactive替代ref来定义items,因为items是一个复杂数据结构,reactive能更高效地处理嵌套数据的变更。 - 创建一个
setInputRef函数,它返回一个回调函数,该回调函数在每个输入框的ref属性中使用。这个回调会在DOM元素挂载时被调用,将元素引用保存到inputRefs数组的对应索引位置。 - 通过
watchEffect监视items的任何变化,自动调整inputRefs数组的长度,确保两者同步。这比使用watch更简洁,因为它会立即执行并自动追踪依赖。 - 移除了
onMounted中的初始化逻辑,因为watchEffect已经足够处理数组的初始化和动态调整。
该方法简洁且充分利用了Vue 3的响应式系统,提供了对动态引用更灵活和高效的管理。