Element表單驗證(2)


Element表單驗證(2)

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

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

  • Options
  • Validate
  • Rules

基本驗證流程如下

  • 先按照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.name

很重要的一點,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節點上的屬性中。然后上面還有一個不好的一點。那就是規則的定義方式不夠靈活。

比如我有兩個字段firstNamelastNamefirstName是必填的,而lastName是非必填的;且firstName長度要求大於1小於4而lastName要求大於1小於6。那么就要寫兩個不同的規則,現在只是2個字段而已,沒什么,如果有很多個不同要求的字段,那要寫很多個不同的規則,也要寫很多個規則?豈不是很煩?能不能復用?

Rules三種定義方式

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

函數的方式很強大,如果需要用到options可以函數的方式,最常用的是對象和數組的方式。現在推薦幾種復用的方法。

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

// 返回一個規則數組,必填且字符串長度在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
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM