需求描述
- 最近有一個需求,就是用户説,不習慣使用tab鍵做輸入框input的光標切換
- (tab鍵盤沒法回到之前的input光標,只能走了一圈後再回到原點那種)
- 用户喜歡使用上下左右鍵,來進行輸入框切換
- 基於這個需求下,便有了本篇文章的示例
- 示例演示網站:http://ashuai.work:8890/30
- github:https://github.com/shuirongshuifu/vue3-echarts5-example
- 我們先看一下下方效果圖:
需求效果圖
需求思路
- 因為是通過上下左右鍵去控制,所以需要區分
event.key為ArrowUp或ArrowDown或ArrowLeft或ArrowRight做對應邏輯控制 - 而後把對應的下一個輸入框給
focus()且select() - 即:
Input.focus()和Input.select(); - 方然,也要
event.preventDefault(); - 在講解代碼之前,我們先來複習一下常用的input標籤元素常用的方法
前置知識——Input元素常用方法
- 開發中常用的input實例的方法就是focus()和blur()比較多
- 實際上還有其他的方法,如:
Input.select()選中輸入框中所有的文本Input.setSelection(start, end)選中輸入框中部分文本start, end起始和結束位置Input.setRangeText(newText, start, end)選中輸入框中部分文本start, end起始和結束位置後,並做替換- 針對於數字輸入框,使用
stepUp或者stepDown可以控制增加或者減少數字的值 - 此外,還有
checkValidity()、setCustomValidity()、reportValidity()用於做輸入框表單的校驗 - 組件化開發中,用的不多,這三個瞭解即可
- 我們看一下下面的效果圖:
Input效果圖
select()
function selectInput() {
textInput.focus();
textInput.select();
result.textContent = "調用了 select() 方法 - 選中了文本輸入框中的所有文本";
}
setSelectionRange()
function setSelection() {
textInput.focus();
if (textInput.value.length >= 7) {
textInput.setSelectionRange(3, 7);
result.textContent = "調用了 setSelectionRange(3,7) - 選中第3到第7個字符";
} else {
result.textContent = "文本太短,無法選擇3-7位置";
}
}
setRangeText()
function setRangeText() {
textInput.focus();
if (textInput.value.length >= 7) {
textInput.setRangeText('新文本', 3, 7);
result.textContent = "調用了 setRangeText('新文本',3,7) - 替換了第3到第7個字符";
} else {
result.textContent = "文本太短,無法替換3-7位置";
}
}
stepUp()
function stepUpInput() {
numberInput.stepUp();
result.textContent = `調用了 stepUp() - 數值變為: ${numberInput.value}`;
}
function stepUpBy3() {
numberInput.stepUp(3);
result.textContent = `調用了 stepUp(3) - 數值變為: ${numberInput.value}`;
}
stepDown()
function stepDownInput() {
numberInput.stepDown();
result.textContent = `調用了 stepDown() - 數值變為: ${numberInput.value}`;
}
function stepDownBy3() {
numberInput.stepDown(3);
result.textContent = `調用了 stepDown(3) - 數值變為: ${numberInput.value}`;
}
完整代碼
複製粘貼即用演示
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Input方法常用示例</title>
<style>
body {
width: 1000px;
margin: 0 auto;
}
.container {
display: flex;
flex-direction: column;
gap: 12px;
}
button {
padding: 8px 12px;
margin: 2px;
cursor: pointer;
}
.logArea {
margin-top: 20px;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
display: flex;
align-items: center;
}
.inputGroup {
margin: 8px 2px;
display: flex;
align-items: center;
}
</style>
</head>
<body>
<h2>Input元素常用方法演示</h2>
<div class="container">
<div class="inputGroup">
<div>文本輸入框:</div>
<input type="text" id="textInput" value="這是一個示例文本">
</div>
<div class="inputGroup">
<div>數字輸入框:</div>
<input type="number" id="numberInput" value="4" min="0" max="20" step="1">
</div>
<div>
<h4>文本操作方法:</h4>
<button onclick="focusInput()">focus()</button>
<button onclick="blurInput()">blur()</button>
<button onclick="selectInput()">select()</button>
<button onclick="setSelection()">setSelectionRange(3,7)</button>
<button onclick="setRangeText()">setRangeText('新文本',3,7)</button>
</div>
<div>
<h4>數字操作方法:</h4>
<button onclick="stepUpInput()">stepUp()</button>
<button onclick="stepDownInput()">stepDown()</button>
<button onclick="stepUpBy3()">stepUp(3)</button>
<button onclick="stepDownBy3()">stepDown(3)</button>
</div>
<div class="logArea">
<div>操作結果:</div>
<div id="result"></div>
</div>
</div>
<script>
const textInput = document.getElementById('textInput');
const numberInput = document.getElementById('numberInput');
const result = document.getElementById('result');
function focusInput() {
textInput.focus();
result.textContent = "調用了 focus() 方法 - 文本輸入框獲得焦點";
}
function blurInput() {
textInput.blur();
result.textContent = "調用了 blur() 方法 - 文本輸入框失去焦點";
}
function selectInput() {
textInput.focus();
textInput.select();
result.textContent = "調用了 select() 方法 - 選中了文本輸入框中的所有文本";
}
function setSelection() {
textInput.focus();
if (textInput.value.length >= 7) {
textInput.setSelectionRange(3, 7);
result.textContent = "調用了 setSelectionRange(3,7) - 選中第3到第7個字符";
} else {
result.textContent = "文本太短,無法選擇3-7位置";
}
}
function setRangeText() {
textInput.focus();
if (textInput.value.length >= 7) {
textInput.setRangeText('新文本', 3, 7);
result.textContent = "調用了 setRangeText('新文本',3,7) - 替換了第3到第7個字符";
} else {
result.textContent = "文本太短,無法替換3-7位置";
}
}
function stepUpInput() {
numberInput.stepUp();
result.textContent = `調用了 stepUp() - 數值變為: ${numberInput.value}`;
}
function stepDownInput() {
numberInput.stepDown();
result.textContent = `調用了 stepDown() - 數值變為: ${numberInput.value}`;
}
function stepUpBy3() {
numberInput.stepUp(3);
result.textContent = `調用了 stepUp(3) - 數值變為: ${numberInput.value}`;
}
function stepDownBy3() {
numberInput.stepDown(3);
result.textContent = `調用了 stepDown(3) - 數值變為: ${numberInput.value}`;
}
</script>
</body>
</html>
方式一
html
<template>
<div class="box1">
<el-table :data="tableData" border style="width: 400px">
<el-table-column width="72px" prop="time" label="時間" align="center">
</el-table-column>
<el-table-column prop="dazhong" label="大眾">
<template #default="scope">
<el-input @keydown="handleKeyDown(scope.$index, 0, $event)"
oninput="value=value.replace(/^\.+|[^\d.]/g,'')" maxlength="3"
v-model.trim="scope.row.dazhong" />
</template>
</el-table-column>
<el-table-column prop="tongyong" label="通用">
<template #default="scope">
<el-input @keydown="handleKeyDown(scope.$index, 1, $event)"
oninput="value=value.replace(/^\.+|[^\d.]/g,'')" maxlength="3"
v-model.trim="scope.row.tongyong" />
</template>
</el-table-column>
<el-table-column prop="jipu" label="吉普">
<template #default="scope">
<el-input @keydown="handleKeyDown(scope.$index, 2, $event)"
oninput="value=value.replace(/^\.+|[^\d.]/g,'')" maxlength="3" v-model.trim="scope.row.jipu" />
</template>
</el-table-column>
<el-table-column prop="fengtian" label="豐田">
<template #default="scope">
<el-input @keydown="handleKeyDown(scope.$index, 3, $event)"
oninput="value=value.replace(/^\.+|[^\d.]/g,'')" maxlength="3"
v-model.trim="scope.row.fengtian" />
</template>
</el-table-column>
</el-table>
</div>
</template>
- 注意,我們直接使用e就行了
- 即:
@keydown="handleKeyDown(scope.$index, 2, $event)" - 這裏需要手動指定列的索引,比如上述的
2。行的索引直接使用scope.$index即可 - 後續就是通過行列的索引,來獲取下一個輸入框並聚焦和選中文本
表格模擬數據
const tableData = ref([
{
time: "第一組",
dazhong: 1,
tongyong: 2,
jipu: 3,
fengtian: 4,
},
{
time: "第二組",
dazhong: 5,
tongyong: 6,
jipu: 7,
fengtian: 8,
},
{
time: "第三組",
dazhong: 9,
tongyong: 10,
jipu: 11,
fengtian: 12,
},
{
time: "第四組",
dazhong: 13,
tongyong: 14,
jipu: 15,
fengtian: 16,
},
]);
關鍵控制代碼
const handleKeyDown = (rowIndex, colIndex, event) => {
const key = event.key;
let nextRow = rowIndex;
let nextCol = colIndex;
if (key === "ArrowUp") {
nextRow = Math.max(0, rowIndex - 1);
} else if (key === "ArrowDown") {
nextRow = Math.min(tableData.value.length - 1, rowIndex + 1);
} else if (key === "ArrowLeft") {
nextCol = Math.max(0, colIndex - 1);
} else if (key === "ArrowRight") {
nextCol = Math.min(3, colIndex + 1);
} else {
return;
}
event.preventDefault();
// 獲取下一個輸入框並聚焦和選中文本
const nextInput = document.querySelectorAll(".box1 .el-input__inner")[nextRow * 4 + nextCol];
if (nextInput) {
nextInput.focus();
nextInput.select();
}
};
方式二的js邏輯
- html不變,js思路都是一樣的
- 基於此,實際上可以擴展n行n列(上文是4行4列)
const columnCount = 4; // 數據列的數量
const handleKeyDown = (rowIndex, colIndex, event) => {
const key = event.key;
let nextRow = rowIndex;
let nextCol = colIndex;
if (key === "ArrowUp") {
if (rowIndex === 0) {
nextRow = tableData.value.length - 1;
} else {
nextRow = rowIndex - 1;
}
} else if (key === "ArrowDown") {
if (rowIndex === tableData.value.length - 1) {
nextRow = 0;
} else {
nextRow = rowIndex + 1;
}
} else if (key === "ArrowLeft") {
if (colIndex === 0) {
if (rowIndex === 0) {
nextRow = tableData.value.length - 1;
nextCol = columnCount - 1;
} else {
nextRow = rowIndex - 1;
nextCol = columnCount - 1;
}
} else {
nextCol = colIndex - 1;
}
} else if (key === "ArrowRight") {
if (colIndex === columnCount - 1) {
if (rowIndex === tableData.value.length - 1) {
nextRow = 0;
nextCol = 0;
} else {
nextRow = rowIndex + 1;
nextCol = 0;
}
} else {
nextCol = colIndex + 1;
}
} else {
return;
}
event.preventDefault();
// 獲取下一個輸入框並聚焦和選中文本
const nextInput = document.querySelectorAll(".box2 .el-input__inner")[
nextRow * columnCount + nextCol
];
if (nextInput) {
nextInput.focus();
nextInput.select();
}
};
A good memory is not as good as a bad pen...