Element表單驗證(2)

Element表單驗證(2)

上篇講的是async-validator的基本要素,那麼,如何使用到Element中以及怎樣優雅地使用,就在本篇。html

上篇講到async-validator由3大部分組成數組

  • Options
  • Validate
  • Rules

基本驗證流程以下dom

  • 先按照rule的規則,制定每一個字段的規範,生成rules
  • 根據rules生成驗證器const validator = new Validator(rules)
  • 驗證器有驗證函數validator.validate(source, callback)
  • source中的字段對應規則中的字段,全都經過或出錯後調用callback

上面中的validator.validate對應Element中的this.$refs[refName].validate,只不過被改裝過的。並且在Element中定義<el-form :model='form'>:model='form',那個form就是sourcesource的字段名,如source.name就是form.name,那麼只要在<el-form-item prop='name'>設置和source同樣的字段名name,就能夠匹配<el-form :rules='rules'>中的rules.nameasync

很重要的一點,rules.字段名要和source.字段名要同樣纔會驗證。函數

<template>
  <el-form :model='form' ref='domForm' :rules='rules'>
    <el-form-item prop='name' lable='名字'>
      <el-input v-model='form.name'>
    </el-form-item>
  </el-form>
</template>
export default {
  data() {
    this.rules = {
      name: { type: 'string', required: true, trigger: 'blur' }
    }

    return {
      form: {
        name: ''
      }
    }
  },
  methods: {
    submit() {
      this.$refs.domForm.validate(valid => {
        if (!valid) {
          // 驗證不經過
        }

        // 驗證經過後的處理...
      })
    }
  }
}

上面中validate(callback)函數已經添加到form元素DOM節點上的屬性中。而後上面還有一個很差的一點。那就是規則的定義方式不夠靈活。ui

好比我有兩個字段firstNamelastNamefirstName是必填的,而lastName是非必填的;且firstName長度要求大於1小於4而lastName要求大於1小於6。那麼就要寫兩個不一樣的規則,如今只是2個字段而已,沒什麼,若是有不少個不一樣要求的字段,那要寫不少個不一樣的規則,也要寫不少個規則?豈不是很煩?能不能複用?this

Rules三種定義方式url

  • 函數的方式:{ name(rule, value, callback, source, options) {} }
  • 對象的方式: { name: { type: 'string', required: true } }
  • 數組的方式: { name: [{ type: 'string' }, { required: true }] }

函數的方式很強大,若是須要用到options能夠函數的方式,最經常使用的是對象和數組的方式。如今推薦幾種複用的方法。code

簡單的封裝一些經常使用的規則

// 返回一個規則數組,必填且字符串長度在2~10之間
export const name = (msg, min = 2, max = 10, required = true) => ([
  { required, message: msg, trigger: 'blur' },
  { min, max, message: `長度在${min}~${max}個字符`, trigger: 'blur' }
])

// 郵箱
export const email = (required = true) => ([
  { required, message: '請輸入郵箱', trigger: 'blur' },
  { type: 'email', message: '郵箱格式不對', trigger: 'blur' }
])

/* 自定義驗證規則 */

// 大於等於某個整數
const biggerAndNum = num => (rule, v, cb) => {
  const isInt = /^[0-9]+$/.test(v)
  if (!isInt) {
    return cb(new Error('要求爲正整數'))
  }

  if (v < num) {
    return cb(new Error(`要求大於等於${num}`))
  }
  return cb()
}

export const biggerInt = (int, required = true) => ([
  { required, message: '必填', trigger: 'blur' },
  { validator: biggerAndNum(int), trigger: 'blur' }
])

封裝一個專門建立規則的類,鏈式調用

export default class CreateRules {
  constructor() {
    super()
    this.rules = []
  }

  need(msg = '必填', trigger = 'blur') {
    this.rules.push({
      required: true,
      message: msg,
      trigger
    })
    return this
  }
  
  url(message = '不是合法的連接', trigger = 'blur') {
    this.rules.push({
      type: 'url',
      trigger,
      message
    })
    return this
  }

  get() {
    const res = this.rules
    this.rules = []
    return res
  }
}

const createRules = new CreateRules()

//規則
const needUrl = createRules.need().url().get()
const isUrl = createRules.url().get()

// imgUrl必填且是連接;href可選不填,若是填寫必須是連接
const rules = {
  imgUrl: needUrl,
  href: isUrl
}

// deep rule 定義
// urls是數組,長度大於1
// urls的元素是連接
const urls = ['http://www.baidu.com', 'http://www.baidu.com']

const rules = {
  urls: {
    type: 'array',
    min: 1,
    defaultField: isUrl
  }
}
相關文章
相關標籤/搜索