Vue3 + TypeScript + Element Plus + el-input 输入框列表按回车聚焦到下一行

应用效果:从第一行输入1,按回车,聚焦到第二行输入2,按回车,聚焦到第三行......

一、通过元素 id,聚焦到下一行的输入框

关键技术点:

1、动态设置元素 id 属性为::id="`input-apply-amount-${(option as IReagentOption).id}`"

2、设置回车监听:@keyup.enter.native="onEnterPressDown((option as IReagentOption).id)"

html 复制代码
                <el-input
                  ......
                  :id="`input-apply-amount-${(option as IReagentOption).id}`"
                  @keyup.enter.native="onEnterPressDown((option as IReagentOption).id)" />

3、通过 document.getElementById 获取到指定元素

4、focus 和 select,聚焦、全选

TypeScript 复制代码
// 通过元素 id,聚焦到下一行的输入框
const focusNextRowByElementId = (objId: number) => {
  // 通过 objId 获取当前行索引
  let currentRowIndex = selectedOptionIds.value.indexOf(objId);
  // 下一行的输入框
  let nextInput: HTMLInputElement;
  if (currentRowIndex + 1 < selectedOptionIds.value.length) {
    // 下一行索引的 objId
    let nextRowObjId = selectedOptionIds.value[currentRowIndex + 1];
    nextInput = document.getElementById(`input-apply-amount-${nextRowObjId}`) as HTMLInputElement;
  } else {
    // 最后一行聚焦到申领用途输入框
    nextInput = document.getElementById("transfer-right-footer-purpose-input") as HTMLInputElement;
  }
  nextInput?.focus();
  nextInput?.select();
};

二、通过元素 ref,聚焦到下一行的输入框

关键技术点:

1、动态设置元素 ref 属性为::ref="`input-apply-amount-${(option as IReagentOption).id}`"

2、设置回车监听:@keyup.enter.native="onEnterPressDown((option as IReagentOption).id)"

html 复制代码
                <el-input
                  ......
                  :ref="`input-apply-amount-${(option as IReagentOption).id}`"
                  @keyup.enter.native="onEnterPressDown((option as IReagentOption).id)" />

3、通过 getCurrentInstance() 获取当前组件实例,再通过 refs 获取到元素列表

4、focus 和 select,聚焦、全选

TypeScript 复制代码
<script setup lang="ts" name="ReagentApplyDialog">
......
import { getCurrentInstance } from "vue";

// 当前组件实例,相当 vue2 的this
const thisInstance = getCurrentInstance();

// 通过元素 ref,聚焦到下一行的输入框
const focusNextRowByElementRef = (objId: number) => {
  if (!thisInstance) return;

  // 获取输入框实例 Record
  let refs = thisInstance.refs as Record<string, HTMLInputElement>;

  // 通过 objId 获取当前行索引
  let currentRowIndex = selectedOptionIds.value.indexOf(objId);
  if (currentRowIndex + 1 < selectedOptionIds.value.length) {
    // 下一行索引的 objId
    let nextRowObjId = selectedOptionIds.value[currentRowIndex + 1];
    // 聚焦到下一行的输入框
    refs[`input-apply-amount-${nextRowObjId}`].focus();
    refs[`input-apply-amount-${nextRowObjId}`].select();
  } else {
    // 最后一行聚焦到申领用途输入框
    refs["transfer-right-footer-purpose-input"].focus();
    refs["transfer-right-footer-purpose-input"].select();
  }
};
......
</script>

实例完整代码:

html 复制代码
<script setup lang="ts" name="ReagentApplyDialog">
......
import { getCurrentInstance, nextTick, onMounted, ref, watch } from "vue";

// 当前组件实例,相当 vue2 的this
const thisInstance = getCurrentInstance();

// 按回车,申领数量输入框按回车
const onEnterPressDown = (objId: number) => {
  // 奇数
  if (objId % 2 === 1) {
    // 通过元素 id,聚焦到下一行的输入框
    focusNextRowByElementId(objId);
  }
  // 偶数
  else {
    // 通过元素 ref,聚焦到下一行的输入框
    focusNextRowByElementRef(objId);
  }
};

// 通过元素 id,聚焦到下一行的输入框
const focusNextRowByElementId = (objId: number) => {
  // 通过 objId 获取当前行索引
  let currentRowIndex = selectedOptionIds.value.indexOf(objId);
  // 下一行的输入框
  let nextInput: HTMLInputElement;
  if (currentRowIndex + 1 < selectedOptionIds.value.length) {
    // 下一行索引的 objId
    let nextRowObjId = selectedOptionIds.value[currentRowIndex + 1];
    nextInput = document.getElementById(`input-apply-amount-${nextRowObjId}`) as HTMLInputElement;
  } else {
    // 最后一行聚焦到申领用途输入框
    nextInput = document.getElementById("transfer-right-footer-purpose-input") as HTMLInputElement;
  }
  nextInput?.focus();
  nextInput?.select();
};

// 通过元素 ref,聚焦到下一行的输入框
const focusNextRowByElementRef = (objId: number) => {
  if (!thisInstance) return;

  // 获取输入框实例 Record
  let refs = thisInstance.refs as Record<string, HTMLInputElement>;

  // 通过 objId 获取当前行索引
  let currentRowIndex = selectedOptionIds.value.indexOf(objId);
  if (currentRowIndex + 1 < selectedOptionIds.value.length) {
    // 下一行索引的 objId
    let nextRowObjId = selectedOptionIds.value[currentRowIndex + 1];
    // 聚焦到下一行的输入框
    refs[`input-apply-amount-${nextRowObjId}`].focus();
    refs[`input-apply-amount-${nextRowObjId}`].select();
  } else {
    // 最后一行聚焦到申领用途输入框
    refs["transfer-right-footer-purpose-input"].focus();
    refs["transfer-right-footer-purpose-input"].select();
  }
};
......
</script>

<template>
......
        <el-transfer
          ......>
          <!-- 自定义列表数据项的内容 -->
          <template #default="{ option }">
                ......
                <el-input
                  v-if="selectedOptionIds.includes((option as IReagentOption).id)"
                  :ref="`input-apply-amount-${(option as IReagentOption).id}`"
                  :id="`input-apply-amount-${(option as IReagentOption).id}`"
                  class="input-apply-amount"
                  style="width: 85px; text-align: center"
                  v-model="(option as IReagentOption).applyAmount"
                  placeholder="输入申领数量"
                  size="small"
                  clearable
                  @input="(option as IReagentOption).applyAmount = Number(formatToNumber($event, 0))"
                  @keyup.enter.native="onEnterPressDown((option as IReagentOption).id)" />
                ......
          </template>
        </el-transfer>
......
</template>
相关推荐
Highcharts.js7 小时前
数据可视化避坑指南 ——开发中常见图表错误与修复方案
javascript·信息可视化·数据可视化·highcharts·数据可视化避坑·修复方案
观无8 小时前
若依EasyExcel实现单元格合并
开发语言·前端·javascript
愚公搬代码8 小时前
【愚公系列】《Web应用安全》001-VMware的安装
前端·安全
xiaohaiAIgeo8 小时前
【2026年】HG/T 20656-2024化工暖通空调设计规范:新版标准的变化与影响
java·前端·javascript·科普知识
立少→万能汉编8 小时前
用“立少→超文本”写静态网页,标签<倍>
服务器·前端·javascript
weixin_431600448 小时前
NestJS 入门(7):生命周期钩子——构造函数和 `OnModuleInit` 差在哪?
前端·后端·学习·node.js·nest.js
你挚爱的强哥9 小时前
【chromeDownload】自定义组件:多用于登录框底部提供下载Chrome谷歌浏览器的链接
前端·vue.js·chrome
cindershade9 小时前
用原生 HTML5 视频与 Canvas 实现浏览器端视频抽帧封面
前端
笨鸟先飞,勤能补拙9 小时前
Web 服务器与计算机网络全景原理
运维·服务器·前端·网络·人工智能·计算机网络·web安全
NutShell Wang9 小时前
Wails v3 Beta 实战:用显式对象模型重写你的第一个 Go 桌面应用
前端·人工智能·go·vibe coding