#在建立專案前這裡我們首先要說明的是,我們使用的版本狀況
Nodejs:v17.5.0
pnpm:7.0.0
#Vue:3.2.25
#首先我們Vite 建立一個vue3 的項目demo,名字就叫做FormValidate, 我們在命令列輸入指令
pnpm create vite FormValidate
回車
然後選擇vue
繼續回車,說明我們已經初步建立了FormValidate (表單驗證)項目
根據命令列的提示,我們進入專案根目錄,然後使用命令pnpm install
安裝專案所需的依賴,當然這裡使用pnpm 是比npm 或yarn 快很多的。
接著,我們啟動專案pnpm run dev
, 終端機中輸出如圖內容
vite v2.9.7 dev server running at: > Local: http://localhost:3000/ > Network: use `--host` to expose ready in 954ms.
啟動瀏覽起,輸入位址http://localhost:3000 /
ok, 到這裡我們已經把項目搭建起來了,結下來我們就開始來說說我們今天主題-表單驗證
這裡我們使用async-validator 這是一個非同步驗證表單的插件,在github上有5k 的star,使用的也很廣泛,例如Ant.design
, Element UI
, Naive UI
等都在使用這個插件,甚至與有些Nodejs後端專案也在使用這個。
先安裝這個插件,在命令列輸入
pnpm install async-validator
這裡async-validator
版本是4.1.1
開啟專案中的App.vue 文件,刪除多餘的文件內容,輸入標題vue3 表單驗證,並且加入一些初始程式碼
<template> <div class="main"> <h4>vue3 表单验证</h4> <form> <div> <label class="label">账号</label> <input type="text" placeholder="请输入账号" class="input" /> </div> <div> <label class="label">密码</label> <input tyep="password" type="text" class="input" placeholder="请输入密码" /> </div> <div> <button>保存</button> </div> </form> </div> </template> <script setup> </script> <style lang="css"> .main{ text-align:center; } .label { padding-right: 10px; padding-left: 10px; display: inline-block; box-sizing: border-box; width: 100px; text-align: right; } .input { width: 200px; height: 30px; margin-top:10px; } </style>
是不是看起來有點醜,別急,我們加點css程式碼,簡單的美化一下
<template> <div class="main"> <h4>Vue3表单验证</h4> <form class="form-box"> <div class="form-group "> <label class="label">账号</label> <input type="text" class="input" placeholder="请输入账号" /> </div> <div class="form-group"> <label class="label">密码</label> <input tyep="password" type="text" placeholder="请输入密码" class="input" /> </div> <div class="form-group"> <button class="btn ">保存</button> </div> </form> </div> </template> <script setup> </script> <style scoped> .main { text-align: center; } .btn{ margin: 0; line-height: 1; padding: 15px; height: 30px; width: 60px; font-size: 14px; border-radius: 4px; color: #fff; background-color: #2080f0; white-space: nowrap; outline: none; position: relative; border: none; display: inline-flex; flex-wrap: nowrap; flex-shrink: 0; align-items: center; justify-content: center; user-select: none; text-align: center; cursor: pointer; text-decoration: none; } .form-box{ width: 500px; max-width: 100%; margin: 0 auto; padding: 10px; } .form-group{ margin: 10px; padding: 10px 15px 10px 0 } .label { padding-right: 10px; padding-left: 10px; display: inline-block; box-sizing: border-box; width: 110px; text-align: right; } .input { width: calc(100% - 120px); height: 28px; } </style>
引入ref
屬性和async-validator
,這裡我們為每個input 框新增v-model
綁定屬性,
// html <input type="text" v-model="form.account" class="input" placeholder="请输入账号" /> <input tyep="password" v-model="form.password" type="text" placeholder="请输入密码" class="input" /> // script import { ref } from "vue" import Schema from 'async-validator'; const form = ref({ account: null, password: null, })
根據表單的情況,我們定義一個對象,這個對象裡面存儲了需要校驗的對象和校驗不通過時的信息
const rules = { account: { required: true, message: '请输入账号' }, password: { required: true, message: '请输入密码' } }
實例化Schema, 將rules 傳入Schema,得到一個validator
const validator = new Schema(rules)
驗證單一表單我們使用失去焦點事件, 定義一個函數,將這個函數加入到account input上的失焦事件上
// html <input v-model="account" type="text" class="input" @blur="handleBlurAccount" placeholder="请输入账号" /> // script const handleBlurAccount = () => {}
接著將實例化後的校驗器函數寫到handleBlurAccount 中
const handleBlurAccount = () => { validator.validate({account: form.value.account}, (errors, fields) => { if (errors && fields.account) { console.log(fields.account[0].message); return errors } }) }
在account 的input 中測試,我們可以看到在控制台列印出了請輸入帳號 等字
同樣的,我們給密碼框也加入如下程式碼
//html <input v-model="form.password" tyep="password" type="text" @blur="handleBlurPassword" placeholder="请输入密码" class="input" /> //script const handleBlurPassword = () => { validator.validate({password: form.value.password}, (errors, fields) => { if (errors && fields.password) { console.log(errors, fields); console.log(fields.password[0].message); return errors } }) }
當然這裡校驗的只是單一input的,我們接下來說說多個表單的校驗,定義一個點擊事件為submit,將submit事件添加到button上,當然不要忘記阻止瀏覽器預設事件
const submit = (e) => { e.preventDefault(); validator.validate(form.value, (errors, fields) => { if (errors) { for(let key of errors) { console.log(key.message); } return errors } }) }
了上面的方式,async-validator
還提供Promise 的方式,我們把submit 函數中的程式碼修改為如下
validator.validate(form.value).then((value) => { // 校验通过 console.log(value); }).catch(({ errors, fields }) => { console.log(errors); return errors })
點擊儲存,同樣的,我們可以看到控制台已經列印了錯誤訊息,說明我們寫的是合適的
當然有時我們會輸入郵箱,電話號碼等表單,這時候我們就需要添加正則來進行驗證了,我們先添加兩個表單,並添加失焦事件, 正則驗證需要用到async-validator
的屬性pattern,我們將符合要求的正規添加到rules ,程式碼如下所示
<div class="form-group "> <label class="label">电话号码</label> <input v-model="form.phone" type="text" class="input" @blur="handleBlurPhone" placeholder="请输入电话号码" /> </div> <div class="form-group "> <label class="label">邮箱</label> <input v-model="form.email" type="text" class="input" @blur="handleBlurEmail" placeholder="请输入邮箱" /> </div> const form = ref({ account: null, email: null, password: null, }) const rules = { account: { required: true, message: '请输入账号' }, phone: { required: true, pattern: /^1\d{10}$/, message: "请输入电话号码" }, email: { required: true, pattern: /^([a-zA-Z0-9]+[_|_|\-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|_|.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,6}$/, message: "请输入邮箱" }, password: { required: true, message: '请输入密码' } } const handleBlurPhone = () => { validator.validate({ phone: form.value.phone }, (errors, fields) => { if (errors && fields.phone) { console.log(errors, fields); console.log(fields.phone[0].message); return errors } }) } const handleBlurEmail = () => { validator.validate({ email: form.value.email }, (errors, fields) => { if (errors && fields.email) { console.log(errors, fields); console.log(fields.email[0].message); return errors } }) }
當然,測試是沒有問題的
假如你要控製表單輸入內容的長度,可以使用屬性min 和max,我們用account 這個表單作為例子,我們rules 對象的account 中添加這兩個屬性,比如要求帳號最少5個字符,最多10個字符,如下
account: { required: true, min:5, max:10, message: '请输入账号' }
我們也可以使用input 的原生屬性maxLength="10" 來控制使用者的輸入
當我們有多個驗證條件的時候,我們可以把rules 的驗證條件寫成一個數組,我們還是用account 這個表單作為例子,比如帳號要求必須用中文,且帳號最少5個字符,最多10個字符,代碼如下
account: [ { required: true, min:5, max:10, message: '请输入账号' }, { required: true, pattern: /[\u4e00-\u9fa5]/, message: '请输入中文账号' } ],
有時候,我們會有使用自訂驗證函數的情況,以滿足特殊驗證情況,這時候,我們可以這樣做
field:{ required: true, validator(rule, value, callback){ return value === ''; }, message: '值不等于 "".', }
到這裡,vue3的表單驗證功能雛形已經基本上出來了,下面我們對驗證功能進行完善
之前的表单验证虽然已经做出了,但是校验的提示信息是在控制台,这个很不友好,用户也看不到提示,所以这里我们完善下这部分功能
首先我们在 label 边加一个 "*" 表示必填,并且添加样式,给一个红色,醒目一些
<label class="label"> <span>账号</span> <span class="asterisk"> *</span> </label> .asterisk{ color: #d03050; }
我们考虑到 rules
对象中 required
属性的作用,这里使用 vue 的条件判断语句 v-if
来判断,先定义一个函数,名字就叫 getRequired
,然后将 rules.account
,作为参数传进去,这里要重点说明一下,如果考虑封装验证方法,这里可以不用传参,不多说,后面讲到了,我们再说,先看代码
<span class="asterisk" v-if="getRequired(rules.account)"> *</span> const getRequired = (condition) => { if(Object.prototype.toString.call(condition) === "[object Object]") { return condition.required } else if (Object.prototype.toString.call(condition) === "[object Array]") { let result = condition.some(item => item.required) return result } return false }
因为 rules.account
, 有可能是对象或者数组,这里我们加一个判断区别下,如果传递进来的是对象,我们直接将属性required
返回回去,至于required
属性是否存在,这里没有必要多判断。 如果传递进来的是数组,我们使用 some 函数获取下结果,然后再返回.
修改 rules.account
的 required
值为false,星号消失,这里只要有一个required
值为true,那么这个星号就显示
我们接着来添加错误信息的显示与隐藏
我们定义一个对象 modelControl
,这个对象里面动态存储错误信息,
const modelControl = ref({})
接着给 account
的 input
框添加一个自定义属性 prop
, 属性值是 account
, 再加一个div显示错误提示信息
<div class="form-group"> <label class="label"> <span>账号</span> <span class="asterisk" v-if="getRequired(rules.account)"> *</span> </label> <input v-model="form.account" type="text" maxLength="10" class="input" prop="account" @blur="handleBlurAccount" placeholder="请输入账号" /> <div class="input feedback" v-if="modelControl['account']">{{modelControl['account']}}</div> </div> .feedback{ color: #d03050; font-size:14px; margin-top: 3px; text-align:left; margin-left:110px; }
为了动态的显示和隐藏错误信息,我们需要修改失焦事件 和 submit 事件,在事件执行的时候,动态的将值赋予或清除,代码如下
const handleBlurAccount = (e) => { const prop = e.target.attributes.prop.value if (!prop) { return false } validator.validate({ account: form.value.account }, (errors, fields) => { if (errors && fields.account) { console.log(errors, fields); console.log(fields.account[0].message); modelControl.value[prop] = fields[prop][0].message return errors } modelControl.value[prop] = null }) } validator.validate(form.value).then((value) => { // 校验通过 console.log(value); }).catch(({ errors, fields }) => { console.log(errors, fields); for(let key in fields) { modelControl.value[key] = fields[key][0].message } console.log(modelControl); return errors })
到这里 表单的动态验证功能基本算是完成了,但是我们发现,每次错误信息的展示都会使得input框跳动,所以还得调整下样式
.form-group { margin: 2px; padding: 10px 15px 3px 0; height:57px; transition: color .3s ease; }
以上是vue3+async-validator如何實作表單驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!