知其然知其所以然
在前端專案開發中,偶爾會有表單提交的問題:
使用者輸入表單後,不小心按了Enter鍵,導致提前觸發了提交事件?
問題概述
當表單中僅有一個input輸入框時,按下Enter鍵就會自動觸發提交事件,這是為什麼呢?
這裡就要提到一個標準:W3C
文中最後一句話已經解釋了原因:
當表單中只有一個單行文字輸入欄位時,使用者代理應接受在該欄位中按Enter鍵作為提交表單的請求。
既然知道了這種現象不是bug,而是切實的標準後,那我們如何在專案中避免呢,畢竟不是每個專案都希望使用者回車的時候突然就觸發了提交事件的。
為了提升使用者體驗,我將提供幾個實用方案!
實用方案
1、原生表單
程式碼復現
<form>
<input type="text" id="myInput">
<button onclick="submitForm()">Submit</button>
</form>
上述程式碼省略了部分提交事件方法,重點突出表單。
解決方案
方案1
在 input 中新增 onkeydown="if(event.keyCode==13){return false;}" 。
透過監聽 input 輸入框的鍵盤事件來控制表單程序,keyCode的值為13即按下了Enter鍵,返回false,即為取消提交事件。
<form>
<input type="text" id="myInput" onkeydown="if(event.keyCode==13){return false;}">
<button onclick="submitForm()">Submit</button>
</form>
方案2
在 form 標籤中新增 onsubmit="return false;"。
透過主動對form表單新增提交屬性,來控制提交事件,return false即為取消提交。
<form onsubmit="return false;">
<input type="text" id="myInput">
<button type="button" onclick="submitForm()">Submit</button>
</form>
注:有的人可能會困惑,為什麼自己的新增了一樣的程式碼,沒有生效的問題,這裡需要注意一點,就是 button 按鈕的預設事件。
MDN-button
從MDN查詢到,button 在不新增 type 屬性時,預設值是 submit。
所以,如果你按照此方案不生效,請檢查下 button 是否有 type 屬性,或已經寫了 submit ,input 回車仍然會自動提交,請將 button 的 type 屬性改為其他值。
方案3
如果你想保證 dom 元素上的整潔清爽,也可以透過 js 的方式。
使用JavaScript阻止預設行為。
你可以給 input 元素新增一個 keypress 或 keydown 事件監聽器,並在使用者按下Enter鍵時阻止預設行為。
document.getElementById('myInput').addEventListener('keypress', function (event) {
if (event.key === 'Enter') {
event.preventDefault();
}
});
2、Vue + ElementPlus
程式碼復現
<template>
<el-form>
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm">提交</el-button>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
interface IForm {
name: string
}
const form = reactive<IForm>({
name: '',
})
const submitForm = async () => {
if (form.name.trim() === '') {
alert('姓名不能為空')
return
}
alert('提交成功:' + form.name)
}
</script>
這裡用的是 Vue3,vue2+elementUI 也是一樣的效果。方案等同。
解決方案
ElementPlus 文件中已經很貼心了做了提示:ElementPlus-Form
就按照官方給出的方案照做就是:
<el-form @submit.prevent>
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm">提交</el-button>
</el-form-item>
</el-form>
當然,也可以寫成 @submit.native 效果是一樣的。
3、React + Ant Design
程式碼復現
import { Form, Input, Button } from 'antd'
interface FormValues {
username: string
}
const App = () => {
const onFinish = (values: FormValues) => {
console.log('Form values:', values)
}
return (
<Form onFinish={onFinish}>
<Form.Item label="Username" name="username">
<Input />
</Form.Item>
<Form.Item label={null}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
)
}
export default App
解決方案
透過對 input 新增 onKeyDown 監聽鍵盤按鍵來阻止回車提交事件。
import React from 'react'
import { Form, Input, Button } from 'antd'
interface FormValues {
username: string
}
const App = () => {
const onFinish = (values: FormValues) => {
console.log('Form values:', values)
}
// 監聽 onKeyDown 事件,阻止Enter鍵的預設行為
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
e.preventDefault()
}
}
return (
<Form onFinish={onFinish}>
<Form.Item label="Username" name="username">
{/* onKeyDown 事件繫結到 Input 元件 */}
<Input onKeyDown={handleKeyDown} />
</Form.Item>
<Form.Item label={null}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
)
}
export default App
上述方案,總結完畢!
如果小夥伴有其他更好用的方案,可以留言分享~