关于Vue循环列表中input的autofocus属性设置自动聚焦失效问题及解决方案

428 阅读1分钟

今天做了个待办事项的小案例,其中有一条需求是这样的 QQ图片20230113130231.png 我通过v-show控制p标签和input标签进行切换编辑模式,但是input标签显示后还需要再次点击才能输入内容,所以我就想添加一个自动聚焦的效果,也就发现了以下bug。

  • bug:在Vue中,input标签设置autodocus属性使其自动聚焦的方法失效。
  • 解决原理
    1. 当循环内多个DOM节点或组件的ref值相同时,this.$refs.[ref的值]获取的是DOM节点或组件实例构成的数组;
    2. DOM节点或组件的ref值不同时,this.$refs.[ref的值]取到的是对应节点或组件实例
  • 解决方案:
    一开始我是想通过动态设置ref的值,以此获取不同的节点。
    <div v-for="item,index in arr">
        <input type="text" :ref="'inputRef'+index">
    </div>
    
    但是发现,我暂时没什么办法获取到这些ref,所以转念一想,可以利用原理1来实现,通过对应的下标来获取,需要注意的是获取ref需要确保节点或组件已经渲染成功了,因此需要使用this.$nextTick。部分代码如下:
    <!-- 任务列表 -->
    <ul>
      <li class="todo-list" v-for="(item, index) in list" :key="index">
        <input type="checkbox" v-model="item.state" />
        <p
          :class="{
            'todo-list-content': true,
            'notodo-list-content': item.state,
          }"
          v-show="!item.edit"
          @click="editTodo(index)"
        >
          {{ item.content }}
        </p>
        <input
          type="text"
          v-model="item.content"
          v-show="item.edit"
          ref="editInput"
        />
      </li>
    </ul>
    
    editTodo(idx) {
      // 进入编辑状态使input自动聚焦
      this.$nextTick(() => {
        this.list.forEach((item, index) => {
          if (item.edit) {
            this.$refs.editInput[index].focus();
          }
        });
      });
    
    至此,完美解决问题