首頁  >  文章  >  web前端  >  vue3+async-validator如何實作表單驗證

vue3+async-validator如何實作表單驗證

PHPz
PHPz轉載
2023-05-11 09:55:122831瀏覽

    建置vue3的專案

    #在建立專案前這裡我們首先要說明的是,我們使用的版本狀況

    • 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, 到這裡我們已經把項目搭建起來了,結下來我們就開始來說說我們今天主題-表單驗證

    vue3的表單驗證

    這裡我們使用async-validator 這是一個非同步驗證表單的插件,在github上有5k 的star,使用的也很廣泛,例如Ant.design Element UINaive UI 等都在使用這個插件,甚至與有些Nodejs後端專案也在使用這個。

    先安裝這個插件,在命令列輸入

    pnpm install async-validator

    這裡async-validator 版本是4.1.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>

    2.新增驗證

    2-1. 初始化

    引入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 &#39;async-validator&#39;;
    
    const form = ref({
        account: null,
        password: null,
    })

    根據表單的情況,我們定義一個對象,這個對象裡面存儲了需要校驗的對象和校驗不通過時的信息

    const rules = {
        account: { required: true, message: &#39;请输入账号&#39; },
        password: { required: true, message: &#39;请输入密码&#39; }
    }

    實例化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
            }
        })
    }
    2-2. 多個表單的驗證

    當然這裡校驗的只是單一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
            }
        })
    }
    2-3. Promise方式驗證

    了上面的方式,async-validator 還提供Promise 的方式,我們把submit 函數中的程式碼修改為如下

    validator.validate(form.value).then((value) => {
            // 校验通过
            console.log(value);
    }).catch(({ errors, fields }) => {
        console.log(errors);
        return errors
    })

    點擊儲存,同樣的,我們可以看到控制台已經列印了錯誤訊息,說明我們寫的是合適的

    vue3+async-validator如何實作表單驗證

    #2-4. 正規驗證

    當然有時我們會輸入郵箱,電話號碼等表單,這時候我們就需要添加正則來進行驗證了,我們先添加兩個表單,並添加失焦事件, 正則驗證需要用到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: &#39;请输入账号&#39; },
        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: &#39;请输入密码&#39; }
    }
    
    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
            }
        })
    }

    當然,測試是沒有問題的

    2-5. 長度控制

    假如你要控製表單輸入內容的長度,可以使用屬性min 和max,我們用account 這個表單作為例子,我們rules 對象的account 中添加這兩個屬性,比如要求帳號最少5個字符,最多10個字符,如下

    account: { required: true, min:5, max:10, message: &#39;请输入账号&#39; }

    我們也可以使用input 的原生屬性maxLength="10" 來控制使用者的輸入

    2-6. 多個驗證條件

    當我們有多個驗證條件的時候,我們可以把rules 的驗證條件寫成一個數組,我們還是用account 這個表單作為例子,比如帳號要求必須用中文,且帳號最少5個字符,最多10個字符,代碼如下

    account: [
        { required: true, min:5, max:10, message: &#39;请输入账号&#39; },
        { required: true, pattern: /[\u4e00-\u9fa5]/, message: &#39;请输入中文账号&#39; }
    ],
    2-5. 自訂驗證

    有時候,我們會有使用自訂驗證函數的情況,以滿足特殊驗證情況,這時候,我們可以這樣做

    field:{
        required: true,
        validator(rule, value, callback){
          return value === &#39;&#39;;
        },
        message: &#39;值不等于 "".&#39;,
    }

    到這裡,vue3的表單驗證功能雛形已經基本上出來了,下面我們對驗證功能進行完善

    3.优化完善

    之前的表单验证虽然已经做出了,但是校验的提示信息是在控制台,这个很不友好,用户也看不到提示,所以这里我们完善下这部分功能

    首先我们在 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.accountrequired 值为false,星号消失,这里只要有一个required 值为true,那么这个星号就显示

    我们接着来添加错误信息的显示与隐藏

    我们定义一个对象 modelControl,这个对象里面动态存储错误信息,

    const modelControl = ref({})

    接着给 accountinput 框添加一个自定义属性 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[&#39;account&#39;]">{{modelControl[&#39;account&#39;]}}</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中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除