---
title: '11/02 VueJS 教學筆記: 正規表示法'
disqus: hackmd
---
11/02 VueJS 教學筆記: 正規表示法
===
綱要
[TOC]
線上測試工具
---
https://regexr.com/

常用規則
---
[Github範例](https://github.com/fortes1219/vue_0803/blob/0803/src/utils/validate.js)
新增一個`validate.js`並放置於 `src/utils` 下,需要驗證哪些資料就引入對應的項目
```javascript=
// URL
export const reg_url = (val) => {
const validate = /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/
return validate.test(val)
}
// ID (TW)
export const reg_twid = (val) => {
const validate = /^[A-Za-z][12]\d{8}$/
return validate.test(val)
}
// TEL (北北基)
export const reg_telTaipei = (val) => {
const validate = /\d{2}-[2]\d{7}/
return validate.test(val)
}
// 手機號碼 (0987-987-987)
export const reg_phoneType1 = (val) => {
const validate = /\d{4}-\d{3}-\d{3}/
return validate.test(val)
}
// 手機號碼 (0987987987)
export const reg_phoneType2 = (val) => {
const validate = /\d{4}\d{3}\d{3}/
return validate.test(val)
}
// 帶國碼且有'+'的手機號碼 (886+987987987)
export const reg_phoneType3 = (val) => {
const validate = /\d{3}\+\d{3}\d{3}\d{3}/
return validate.test(val)
}
// 帳號是否合法 (字母開頭,允許下底線,6~16碼)
export const reg_account = (val) => {
const validate = /^[a-zA-Z][a-zA-Z0-9_]{5,16}$/
return validate.test(val)
}
// 中低強度的密碼,只能包含數字、字母、下底線,6~18碼
export const reg_pwdCommon = (val) => {
const validate = /^[a-zA-Z][a-zA-Z0-9_]{5,16}$/
return validate.test(val)
}
// 高強度密碼,包含特殊字元,需含有大小寫和數字,8~18碼
export const reg_pwdStrong = (val) => {
const validate = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{7,18}$/
return validate.test(val)
}
// Email
// 以下詳解
```
Email驗證的複雜性
---
先對Email的正確格式有些共同標準的認知,比如:
1. 需要有`@`
2. 英文字開頭,不可由數字起始
3. 帳號通常可以接受`.`、`-`和`_`
4. `@`的前面能接受一個以上的英數與符號組合,如`-abc-`和`.abc.`
5. 符號間不可連接,也不可連續,比如不可能出現`user.-.acount@-mail.-com`
6. `@`後的Domain Name由`.`連接
7. `@`後的Domain Name結尾只能是英文字,不允許如`@any-mail.com123`這般不合理的格式
8. `@`的前後不可有符號
```javascript=
// Email
export const reg_email = (val) => {
const validate = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]+$/
return validate.test(val)
}
```

題解步驟:自定義驗證表單
----
[Github範例](https://github.com/fortes1219/vue_0803/blob/0803/src/components/home/Regexp.vue)
確認`validate.js`已放置於 `src/utils` 下後,我們先來建立基本的表單外觀:
```htmlmixed=
<template>
<div class="page">
<h1>正則表單驗證範例</h1>
<br>
<!--不使用element UI 內建驗證的表單-->
<el-form :model="form" label-width="100px" data-width="30rem">
<el-form-item label="姓名">
<el-input v-model="form.name.value" type="text" placeholder="請輸入姓名" />
<div class="el-form-item__error">{{ form.name.msg }}</div>
</el-form-item>
<el-form-item label="電話號碼">
<el-input v-model="form.tel.value" type="text" placeholder="ex: 02-23033824" @change="nativeValidate(form, 'tel')" />
<div class="el-form-item__error">{{ form.tel.msg }}</div>
</el-form-item>
<el-form-item label="手機號碼">
<el-input v-model="form.phone.value" type="text" placeholder="ex: 0987-987-987" @change="nativeValidate(form, 'phone')" />
<div class="el-form-item__error">{{ form.phone.msg }}</div>
</el-form-item>
<el-form-item label="Email">
<el-input v-model="form.email.value" type="text" placeholder="請輸入電子信箱地址" @change="nativeValidate(form, 'email')" />
<div class="el-form-item__error">{{ form.email.msg }}</div>
</el-form-item>
<el-form-item label="個人網站">
<el-input v-model="form.url.value" type="text" placeholder="ex: https://phchome.com" @change="nativeValidate(form, 'url')" />
<div class="el-form-item__error">{{ form.url.msg }}</div>
</el-form-item>
<div class="row horizontal end">
<el-button @click="nativeSubmit" :disabled="status">SUBMIT</el-button>
</div>
</el-form>
</div>
</template>
```
處理`data`與`methods`的結構並且引入驗證規則:
```javascript=
import { reg_telTaipei, reg_phoneType1, reg_email, reg_url } from "../../utils/validate"
export default {
data() {
return {
form: {
name: { value: '', msg: '' },
tel: { value: '', msg: '' },
phone: { value: '', msg: '' },
email: { value: '', msg: '' },
url: { value: '', msg: '' },
},
submitDisabled: true // 送出按鈕的disabled狀態,true為禁用
}
},
methods: {
// native validate
nativeValidate(target, key) {
let checkTel = reg_telTaipei(target.tel.value)
let checkPhone = reg_phoneType1(target.phone.value)
let checkEmail = reg_email(target.email.value)
let checkURL = reg_url(target.url.value)
const arr = [checkTel, checkPhone, checkEmail, checkURL]
// 驗證未通過則顯示msg內的訊息
switch (key) {
case 'tel':
checkTel == true ? target.tel.msg = '' : target.tel.msg = '電話號碼格式錯誤或未輸入'
break
case 'phone':
checkPhone == true ? target.phone.msg = '' : target.phone.msg = '手機號碼格式錯誤或未輸入'
break
case 'email':
checkEmail == true ? target.email.msg = '' : target.email.msg = 'Email格式錯誤或未輸入'
break
case 'url':
checkURL == true ? target.url.msg = '' : target.url.msg = '網址格式錯誤或未輸入'
break
}
// 用find只會撈回符合條件第一個值的特性,任何一個驗證規則沒通過就不能讓送出表單的按鈕被啟用
let result = arr.find((item) => {
return item == false // 尋找array中的false
})
// 當滿足所有條件後,result已經找不到false,會返回一個undefined,利用來判別此時要不要啟用Button
result == undefined ? this.submitDisabled = false : this.submitDisabled = true
console.log('form: ', arr, result)
},
nativeSubmit() {
if (!this.submitDisabled) { // 如果沒有啟用disabled,代表驗證條件皆符合
this.$message({
message: "登入成功",
type: "success"
})
// 接下來就是進入表單下一步動作,反之阻擋住
} else {
this.$message({
message: "登入失敗",
type: "warning"
})
}
},
}
}
```
使用 element UI 內建表單驗證
---
以內建的方法來配置表單驗證會省下不少工夫,需要在HTML上設定一些特定的 Attribute:
```htmlmixed=
<!--使用element UI 內建驗證 v-bind:rules-->
<!--指定目前使用的v-model,並且給予參照名稱「loginForm」-->
<el-form :model="form2" :rules="rules" ref="loginForm" label-width="100px" data-width="30rem">
<!--form item上指定prop == v-model.key-->
<el-form-item label="姓名" prop="name">
<el-input v-model="form2.name" type="text" placeholder="請輸入姓名" />
</el-form-item>
<el-form-item label="電話號碼" prop="tel">
<el-input v-model="form2.tel" type="text" placeholder="請輸入電話號碼" />
</el-form-item>
<el-form-item label="手機號碼" prop="phone">
<el-input v-model="form2.phone" type="text" placeholder="請輸入手機號碼" />
</el-form-item>
<el-form-item label="Email" prop="email">
<el-input v-model="form2.email" type="text" placeholder="請輸入電子信箱地址" />
</el-form-item>
<el-form-item label="個人網站" prop="url">
<el-input v-model="form2.url" type="text" placeholder="個人網站網址"/>
</el-form-item>
<div class="row horizontal end">
<!--submit()中的參數帶el-form的ref名稱-->
<el-button type="primary" @click="submit('loginForm')">SUBMIT</el-button>
</div>
</el-form>
```
接著設置`data`與`methods`:
```javascript=
export default {
data() {
return {
// form {}
// submitDisabled: true
// ...
form2: {
name: '',
tel: '',
phone: '',
email: '',
url: ''
},
rules: {
tel: [{
required: true,
pattern: /\d{2}-[2]\d{7}/,
message: "電話號碼格式錯誤",
trigger: "blur"
}],
phone: [{
required: true,
pattern: /\d{4}-\d{3}-\d{3}/,
message: "手機號碼格式錯誤",
trigger: "blur"
}],
email: [{
required: true,
pattern: /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]+$/,
message: "Email格式錯誤",
trigger: "blur"
}],
url: [{
required: true,
pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/,
message: "網址格式錯誤",
trigger: "blur"
}]
}
}
},
methods: {
// native validate
// ...
// element UI validate
submit(formName) {
this.$refs[formName].validate(valid => {
console.log("valid: ", valid)
if (valid) {
this.$message({
message: "登入成功",
type: "success"
})
} else {
this.$message({
message: "登入失敗",
type: "warning"
})
return false
}
})
}
}
}
```
###### tags: `VueJS` `Regex`