Vue學習筆記-ElmentUI表單校驗

Elment-UI 的 Form 組件提供了表單驗證的功能:

1.將 Form-Item 的 prop 屬性設(shè)置為需校驗的字段名

2.通過 rules 屬性傳入約定的驗證規(guī)則

  rules: {
            name: [
                { 
                    required: true, //非空校驗
                    message: '提示信息', //校驗提示信息
                    trigger: 'blur'//觸發(fā)條件:blur、change
                }
            ]

踩坑:

1.要驗證輸入只能為數(shù)字時

{type:'number',message:'只能為數(shù)字'}

必須要在v-model后面加上.number,即v-moder.number。這里的驗證會將你輸入的value格式化為number值摘完,在你做自定義校驗的時候踢关,要格外注意,有可能正則表達式?jīng)]有起到效果荷荤,就是因為它自動給你轉(zhuǎn)化格式了

2.自定義校驗

必須要有回調(diào),否則表單無法提交。

data() {
    var newReg1 = (rule, value, callback) => {
      if (value < 0) {
        callback(new Error("不能為負數(shù)"));
      } else {
        callback();  //必須要有回調(diào)袒哥,要不然表單無法提交
      }
    };
   var newReg2 = (rule, value, callback) => {
      let pattrn = /^((?!0)\d+(\.\d{1,2})?)$/g
      if (!pattrn.test(value)) {
        callback(new Error("不能為負數(shù)"));
      } else {
        callback();
      }
    };
    return {
      amountCheck: [
        { validator: newReg1, trigger: "blur" },
        { validator: newReg2, trigger: "blur" },
    //此處可寫多個校驗方法
    ......
      ]
    };
}

3.數(shù)據(jù)綁定

做表單驗證時<el-form-item>必須添加prop屬性,而且prop的名字必須和input框v-model綁定的值一致消略。否則的話堡称,表單驗證就會出錯。

 <el-form-item label="活動名稱" prop="name">
        <el-input v-model="ruleForm.name"></el-input>
  </el-form-item>

不同類型的表單校驗

1.普通輸入驗證

<el-form-item label="活動名稱" prop="name">
    <!-- validate-event屬性的作用是: 輸入時不觸發(fā)表單驗證.提交時再驗證,你也可以設(shè)置成動態(tài)驗證 -->
    <el-input v-model="registData.name" :validate-event="false"></el-input>
  </el-form-item>

  rules: { // 表單驗證規(guī)則
    name: [
      { required: true, message: '請輸入活動名稱' }, // 'blur'是鼠標失去焦點的時候會觸發(fā)驗證
      { min: 3, max: 5, message: '長度在 3 到 5 個字符' }
    ]
  }

2.數(shù)字類型驗證

<el-form-item label="區(qū)域面積" prop="area">
    <!-- 輸入的類型為Number時,需要加一個數(shù)字轉(zhuǎn)換的修飾符,輸入框默認的類型是String類型,但是我試了一下,發(fā)現(xiàn)并不能做驗證,所以自己寫了函數(shù)方法驗證 -->
    <!-- <el-input v-model.number="registData.area" autocomplete="off"></el-input> -->
    <!-- keyup是鼠標彈起事件, autocomplete是input自帶的原生屬性,自動補全功能,on為開啟,off為關(guān)閉 -->
    <el-input v-model="registData.area" @keyup.native="InputNumber('area')" autocomplete="off"></el-input>
  </el-form-item>

  area: [
      // 數(shù)字類型 'number', 整數(shù): 'integer', 浮點數(shù): 'float'
      // {type: 'number', message: '請輸入數(shù)字類型', trigger: 'blur'},
      // {type: 'integer', message: '請輸入數(shù)字類型', trigger: 'change'}, // 'change'是表單的值改變的時候會觸發(fā)驗證
      {required: true, message: '請輸入?yún)^(qū)域面積', trigger: 'blur'}
    ],

    // 自己寫的正則驗證,限制用戶輸入數(shù)字以外的字符
    // 過濾輸入的金額
    InputNumber (property) {
      this.registData[property] = this.limitInputPointNumber(this.registData[property])
    },

    // 驗證只能輸入數(shù)字
    limitInputNumber (val) {
      if (val) {
        return String(val).replace(/\D/g, '')
      }
      return val
    },

    // 限制只能輸入數(shù)字(可以輸入兩位小數(shù))
    limitInputPointNumber (val) {
      if (val === 0 || val === '0' || val === '') {
        return ''
      } else {
        let value = null
        value = String(val).replace(/[^\d.]/g, '') // 清除“數(shù)字”和“.”以外的字符
        value = value.replace(/\.{2,}/g, '.') // 只保留第一個. 清除多余的
        value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
        value = value.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能輸入兩個小數(shù)
        return Number(value)
      }
    },

3.1 嵌套驗證(獨立驗證)

這種情況是一行里有多個輸入框或選擇的情況,這里有兩種方法,第一種是el-form嵌套寫法,驗證是獨立的

image
image
<el-form-item label="活動時間" required>
    <el-col :span="11">
      <el-form-item prop="date1">
        <el-date-picker type="date" placeholder="選擇日期" v-model="registData.date1" style="width: 100%;"></el-date-picker>
      </el-form-item>
    </el-col>
    <el-col class="line" :span="2">-</el-col>
    <el-col :span="11">
      <el-form-item prop="date2">
        <el-time-picker type="fixed-time" placeholder="選擇時間" v-model="registData.date2" style="width: 100%;"></el-time-picker>
      </el-form-item>
    </el-col>
  </el-form-item>

  date1: [
    { type: 'date', required: true, message: '請選擇日期', trigger: 'change' }
  ],
  date2: [
    { type: 'date', required: true, message: '請選擇時間', trigger: 'change' }
  ],

3.2 嵌套驗證(聯(lián)動驗證)

這種是聯(lián)動驗證,適用省級聯(lián)動場景,先選國家后觸發(fā)城市驗證

image
image
<!-- region是一個對象,國家和城市是它的屬性 -->
  <el-form-item label="活動區(qū)域" prop="region">
    <el-select v-model="registData.region.country" placeholder="請選擇國家">
      <el-option label="國家一" value="USA"></el-option>
      <el-option label="國家二" value="China"></el-option>
    </el-select>
    <el-select v-model="registData.region.city" placeholder="請選擇城市">
      <el-option label="城市一" value="shanghai"></el-option>
      <el-option label="城市二" value="beijing"></el-option>
    </el-select>
  </el-form-item>

  region: [
    {
      type: 'object',
      required: true,
      // 這里有兩種處理,一種是自定義驗證,拿到值后自己對屬性進行驗證,比較麻煩
      // validator: (rule, value, callback) => {
      //   console.log(55, value)
      //   if (!value.country) {
      //     callback(new Error('請選擇國家'))
      //   } else if (!value.city) {
      //     callback(new Error('請選擇城市'))
      //   } else {
      //     callback()
      //   }
      // },
      trigger: 'change',
      // 官網(wǎng)提供了對象的嵌套驗證,只需要把需要驗證的屬性,放在fields對象里,就會按順序進行驗證
      fields: {
        country: {required: true, message: '請選擇國家', trigger: 'blur'},
        city: {required: true, message: '請選擇城市', trigger: 'blur'}
      }
    }
  ],

4.圖片上傳驗證(手動觸發(fā)部分驗證方法)

有時候會需要在表單里上傳圖片,但是圖片上傳是一個異步過程,屬性值改變后不會去觸發(fā)驗證規(guī)則

image.png

文件上傳后艺演,不會觸發(fā)form表單的驗證却紧,需要手動調(diào)用校驗方法。

<el-form-item label="活動圖片" prop="fileUrl">
    <el-upload
      :action="action"
      :on-success="handleSuccess"
      :data="uploadData"
      :limit="20"
      list-type="picture-card"
      :on-preview="handlePreview"
      :on-remove="handleRemove">
      <i class="el-icon-plus"></i>
    </el-upload>
  </el-form-item>

  fileUrl: [
    { required: true, message: '請上傳圖片', trigger: 'change' }
  ],

  // 刪除圖片
  handleRemove (file, fileList) {
    this.registData.fileUrl = ''
    // 文件刪除后也要觸發(fā)驗證,validateField是觸發(fā)部分驗證的方法,參數(shù)是prop設(shè)置的值
    this.$refs.registerRef.validateField('fileUrl')
  },

  // 圖片上傳
  handleSuccess (res, file, fileList) {
    // 這里可以寫文件上傳成功后的處理,但是一定要記得給fileUrl賦值
    this.registData.fileUrl = 'fileUrl'
    // 文件上傳后不會觸發(fā)form表單的驗證,要手動添加驗證
    this.$refs.registerRef.validateField('fileUrl')
  },

表單校驗示例:(包含自定義校驗)

<el-form :model="ruleForm" :rules="rules" ref="ruleForm">
  <!--input輸入框-->
  <el-form-item label="活動名稱" prop="name">
        <el-input v-model="ruleForm.name"></el-input>
  </el-form-item>
  
  <!--自定義校驗-->
  <el-form-item label="聯(lián)系電話" prop="phone">
        <el-input v-model="ruleForm.phone"></el-input>
  </el-form-item>

  <!--select下拉框-->
  <el-form-item label="活動區(qū)域" prop="region">
        <el-select v-model="ruleForm.region" placeholder="請選擇活動區(qū)域">
              <el-option label="區(qū)域一" value="shanghai"></el-option>
              <el-option label="區(qū)域二" value="beijing"></el-option>
        </el-select>
  </el-form-item>

  <!--checkout多選框-->
  <el-form-item label="活動性質(zhì)" prop="type">
    <el-checkbox-group v-model="ruleForm.type">
      <el-checkbox label="美食/餐廳線上活動" name="type"></el-checkbox>
      <el-checkbox label="地推活動" name="type"></el-checkbox>
      <el-checkbox label="線下主題活動" name="type"></el-checkbox>
      <el-checkbox label="單純品牌曝光" name="type"></el-checkbox>
    </el-checkbox-group>
  </el-form-item>

  <!--redio單選框-->
  <el-form-item label="特殊資源" prop="resource">
    <el-radio-group v-model="ruleForm.resource">
      <el-radio label="線上品牌商贊助"></el-radio>
      <el-radio label="線下場地免費"></el-radio>
    </el-radio-group>
  </el-form-item>
</el-form>

<script>
  export default {
    data() {
        //手機號
        var validatePhone = (rule, value, callback) => {
          if (/^1[34578]{1}\d{9}$/.test(value) == false) {
            callback(new Error("請輸入正確的手機號"));
          } else {
            callback();
          }
        };
      return {
            rules: {
                name: [
                        { required: true, message: '請輸入活動名稱', trigger: 'blur' },
                        { min: 3, max: 5, message: '長度在 3 到 5 個字符', trigger: 'blur' }
                      ],
                region: [
                        { required: true, message: '請選擇活動區(qū)域', trigger: 'change' }
                      ],
                type: [
                        { type: 'array', required:true,message:'請選擇活動性質(zhì)', trigger: 'change' }
                      ],
                resource: [
                        { required: true, message: '請選擇活動資源', trigger: 'change' }
                      ],
            }
      };
    },
    methods: {
      submitForm(formName) {
        this.$refs[formName].validate((valid) => {
          if (valid) {
            alert('submit!');
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },
      resetForm(formName) {
        this.$refs[formName].resetFields();
      }
    }
  }
</script>

完整代碼:

<template>
  <div>
    <p>shopInfo</p>
    <div class="company" id="company">
      <!-- model是驗證的數(shù)據(jù)來源 -->
      <el-form :model="registData" :rules="rules" ref="registerRef" label-width="100px" class="demo-ruleForm">
        <el-form-item label="活動名稱" prop="name">
          <!-- validate-event輸入時不觸發(fā)表單驗證,提交時再驗證,也可以設(shè)置成動態(tài)驗證 -->
          <el-input v-model="registData.name" :validate-event="false"></el-input>
        </el-form-item>
        <el-form-item label="區(qū)域面積" prop="area">
          <!-- 輸入的類型為Number時,需要加一個數(shù)字轉(zhuǎn)換的修飾符,輸入框默認的類型是String類型,但是我試了一下,發(fā)現(xiàn)并不能做驗證,所以自己寫了函數(shù)方法驗證 -->
          <!-- <el-input v-model.number="registData.area" autocomplete="off"></el-input> -->
          <el-input v-model="registData.area" @keyup.native="InputNumber('area')" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="活動區(qū)域" prop="region">
          <el-select v-model="registData.region.country" placeholder="請選擇國家">
            <el-option label="國家一" value="USA"></el-option>
            <el-option label="國家二" value="China"></el-option>
          </el-select>
          <el-select v-model="registData.region.city" placeholder="請選擇城市">
            <el-option label="城市一" value="shanghai"></el-option>
            <el-option label="城市二" value="beijing"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="活動時間" required>
          <el-col :span="11">
            <el-form-item prop="date1">
              <el-date-picker type="date" placeholder="選擇日期" v-model="registData.date1" style="width: 100%;"></el-date-picker>
            </el-form-item>
          </el-col>
          <el-col class="line" :span="2">-</el-col>
          <el-col :span="11">
            <el-form-item prop="date2">
              <el-time-picker type="fixed-time" placeholder="選擇時間" v-model="registData.date2" style="width: 100%;"></el-time-picker>
            </el-form-item>
          </el-col>
        </el-form-item>
        <el-form-item label="即時配送" prop="delivery">
          <el-switch v-model="registData.delivery"></el-switch>
        </el-form-item>
        <el-form-item label="活動性質(zhì)" prop="type">
          <el-checkbox-group v-model="registData.type">
            <el-checkbox label="美食/餐廳線上活動" name="type"></el-checkbox>
            <el-checkbox label="地推活動" name="type"></el-checkbox>
            <el-checkbox label="線下主題活動" name="type"></el-checkbox>
            <el-checkbox label="單純品牌曝光" name="type"></el-checkbox>
          </el-checkbox-group>
        </el-form-item>
        <el-form-item label="特殊資源" prop="resource">
          <el-radio-group v-model="registData.resource">
            <el-radio label="線上品牌商贊助"></el-radio>
            <el-radio label="線下場地免費"></el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="活動圖片" prop="fileUrl">
          <el-upload
            :action="action"
            :on-success="handleSuccess"
            :data="uploadData"
            :limit="20"
            list-type="picture-card"
            :on-preview="handlePreview"
            :on-remove="handleRemove">
            <i class="el-icon-plus"></i>
          </el-upload>
        </el-form-item>
        <el-form-item label="活動形式" prop="desc">
          <el-input type="textarea" v-model="registData.desc"></el-input>
        </el-form-item>
        <el-form-item>
          <!-- 提交的時候傳入的是表單的ref -->
          <el-button type="primary" @click="submitForm('registerRef')">立即創(chuàng)建</el-button>
          <el-button @click="resetForm('registerRef')">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>
<style scoped>
  .company {
    padding: 30px;
    text-align: left;
    width: 600px;
  }
</style>
<script>
export default {
  name: 'shopInfo',

  data () {
    return {
      registData: {
        name: '', // 名稱
        area: '', // 面積
        region: {}, // 地區(qū)
        date1: '', // 日期
        date2: '', // 時間
        delivery: false, // 即時配送
        type: [], // 活動性質(zhì)
        resource: '', // 特殊資源
        fileUrl: '', // 活動圖片
        desc: '' // 活動形式
      }, // 需要驗證的表單屬性,必須在data中定義
      rules: { // 表單驗證規(guī)則
        name: [
          { required: true, message: '請輸入活動名稱' }, // 'blur'是鼠標失去焦點的時候會觸發(fā)驗證
          { min: 3, max: 5, message: '長度在 3 到 5 個字符' }
        ],
        area: [
          // 數(shù)字類型
          // {type: 'number', message: '請輸入數(shù)字類型', trigger: 'blur'},
          // {type: 'integer', message: '請輸入數(shù)字類型', trigger: 'change'}, // 'change'是表單的值改變的時候會觸發(fā)驗證
          {required: true, message: '請輸入?yún)^(qū)域面積', trigger: 'blur'}
        ],
        region: [
          {
            type: 'object',
            required: true,
            trigger: 'change',
            fields: {
              country: {required: true, message: '請選擇國家', trigger: 'blur'},
              city: {required: true, message: '請選擇城市', trigger: 'blur'}
            }
          }
        ],
        date1: [
          { type: 'date', required: true, message: '請選擇日期', trigger: 'change' }
        ],
        date2: [
          { type: 'date', required: true, message: '請選擇時間', trigger: 'change' }
        ],
        type: [
          { type: 'array', required: true, message: '請至少選擇一個活動性質(zhì)', trigger: 'change' }
        ],
        resource: [
          { required: true, message: '請選擇活動資源', trigger: 'change' }
        ],
        fileUrl: [
          { required: true, message: '請上傳圖片', trigger: 'change' }
        ],
        desc: [
          { required: true, message: '請?zhí)顚懟顒有问?, trigger: 'blur' }
        ]
      },
      action: `https://xxx.com`,
      uploadData: {userId: 1304, pathName: 'company'}
    }
  },
  methods: {
    // 過濾輸入的金額
    InputNumber (property) {
      this.registData[property] = this.limitInputPointNumber(this.registData[property])
    },

    // 驗證只能輸入數(shù)字
    limitInputNumber (val) {
      if (val) {
        return String(val).replace(/\D/g, '')
      }
      return val
    },

    // 限制只能輸入數(shù)字(可以輸入兩位小數(shù))
    limitInputPointNumber (val) {
      if (val === 0 || val === '0' || val === '') {
        return ''
      } else {
        let value = null
        value = String(val).replace(/[^\d.]/g, '') // 清除“數(shù)字”和“.”以外的字符
        value = value.replace(/\.{2,}/g, '.') // 只保留第一個. 清除多余的
        value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
        value = value.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能輸入兩個小數(shù)
        return Number(value)
      }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胎撤,一起剝皮案震驚了整個濱河市晓殊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伤提,老刑警劉巖巫俺,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肿男,居然都是意外死亡介汹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痢毒,你說我怎么就攤上這事「献” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長豪娜。 經(jīng)常有香客問我餐胀,道長,這世上最難降的妖魔是什么瘤载? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任否灾,我火速辦了婚禮,結(jié)果婚禮上鸣奔,老公的妹妹穿的比我還像新娘墨技。我一直安慰自己,他們只是感情好挎狸,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布扣汪。 她就那樣靜靜地躺著,像睡著了一般锨匆。 火紅的嫁衣襯著肌膚如雪崭别。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天恐锣,我揣著相機與錄音茅主,去河邊找鬼。 笑死土榴,一個胖子當著我的面吹牛诀姚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玷禽,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赫段,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了论衍?” 一聲冷哼從身側(cè)響起瑞佩,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤聚磺,失蹤者是張志新(化名)和其女友劉穎坯台,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘫寝,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡蜒蕾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了焕阿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咪啡。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖暮屡,靈堂內(nèi)的尸體忽然破棺而出撤摸,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布准夷,位于F島的核電站钥飞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏衫嵌。R本人自食惡果不足惜读宙,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望楔绞。 院中可真熱鬧结闸,春花似錦、人聲如沸酒朵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔫耽。三九已至察纯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間针肥,已是汗流浹背饼记。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留慰枕,地道東北人具则。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像具帮,于是被迫代替她去往敵國和親博肋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • React中沒有類似Angular那樣的雙向數(shù)據(jù)綁定,在做一些表單復雜的后臺類頁面時掘猿,監(jiān)聽病游、賦值、傳遞稠通、校驗時編碼...
    tedyuen777閱讀 9,865評論 1 23
  • 什么是組件衬衬? 組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素改橘,封裝...
    youins閱讀 9,479評論 0 13
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5滋尉? 答:HTML5是最新的HTML標準。 注意:講述HT...
    kismetajun閱讀 27,474評論 1 45
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容飞主,還有我對于 Vue 1.0 印象不深的內(nèi)容狮惜。關(guān)于...
    云之外閱讀 5,048評論 0 29
  • 最近在跟著網(wǎng)上的教程熟悉 docker 的用法高诺,誰知連 Hello World 都失敗了,在此記錄一下碾篡。 在 gi...
    弄碼哥nomag閱讀 1,019評論 1 0