阅读 157

【Vue Validator】自己写表单验证

背景

因为是写一个C端网站,所以不用el-element

需求

对登录窗口输入做验证,并做提示

方案

要点

  • 提示语html 采用v-if
  • 验证使用公认的async-validator
  • 验证与显示之间 利用vue响应原理

步骤

  1. 引入,实例化
import Schema from 'async-validator'

const rules = {
    username: { required: true, message: '请输入用户名' },
    password: { required: true, message: '请输入密码' }
}
const validator = new Schema(rules)
复制代码
// data
data() {
    // 表单数据
    form: {
        username: '',
        password: ''
    },
    // 验证control
    validatorControl: {}
}
复制代码
  1. 验证单个和整体

验证单个使用失去焦点事件,整体要能异步回调

// methods
methods: {
// mounted 初始化control
validatorInit() {
    for (const key in rules) {
        // control 属性对应rules,v-if 对应 false 与 message(message不应为空)
        this.$set(this.validatorControl, key, false)
    }
},

validate(e) {
    const control = this.validatorControl
    
    if (e) {
    // 验证单个元素
        // 验证input添加prop属性(如下面input所示)
        const prop = e.target?.attributes?.prop?.value
        if (!prop) return
        // 清理control
        control[prop] = false
        validator.validate(this.form, (errors, fields) => {
            if (errors && fields[prop]) control[prop] = fields[prop][0].message
        })
    } else {
    // 验证整个元素
        for (const key in control) {
            control[key] = false
        }
        // async-validator 是异步返回,所以需要Promise传递结果
        return new Promise((resolve, reject) => {
            validator.validate(this.form, (errors, fields) => {
                if (errors)
                    errors.forEach(item => {
                        this.validatorControl[item.field] = item.message
                    })
                else resolve(true)
                resolve(false)
                })
            })
        }
    },
}
复制代码
  1. 绑定html属性,绑定焦点事件
// blur事件不会冒泡,所以要用focusout,但要注意button一类也会发生focusout
<div class="form" @focusout="validate">
<vs-input v-model="form.username" prop="username">
        <template v-if="validatorControl.username" #message-danger>{{ validatorControl.username }}</template>
    </vs-input>
    <vs-input type="password" v-model="form.password" prop="password">
        <template v-if="validatorControl.password" #message-danger>{{ validatorControl.password }}</template>
    </vs-input>
</div>
复制代码
  1. click方法
async login() {
    // 异步等待
    if (!(await this.validate())) return
    ...
}
复制代码

完成

image.png

注意

  • async-validator没有单独验证某个字段功能,所以只能筛选
  • async-validator不能关闭console.warning
// warning源码,表明只能在生产环境不显示
// don't print warning message when in production env or node runtime
if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined' && typeof document !== 'undefined') {
  warning = function warning(type, errors) {
    if (typeof console !== 'undefined' && console.warn) {
      if (errors.every(function (e) {
        return typeof e === 'string';
      })) {
        console.warn(type, errors);
      }
    }
  };
}
复制代码
  • can i use focusout

image.png

文章分类
前端
文章标签