Vue3 基于主键访问的动态 dom ref 引用示例

200 阅读1分钟

在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的响应式系统,提供了对动态引用更灵活和高效的管理。