讓 VeeValidate 更容易維護

VeeValidate 除了內建很多 Validation Rule,還可以自訂 語系,自訂 訊息,自訂 驗證規則,但要如何這些整合進大型專案架構呢 ?

Version


Vue 2.5.17
VeeValidate 2.1.2

Directory


architecture000

  • src 下建立 validators 目錄,專門存放 VeeValidate 所使用的自訂 validator
  • validators 目錄下建立 config 目錄,專門放置 欄位對照檔VeeValidate 設定檔自訂訊息檔
  • validators 目錄下建立 rules 目錄,專門放置各種 自訂驗證規則檔

Component


demo.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div>
<div>
<input v-model="email" v-validate="'required|email'" name="emailAddress" type="text">
</div>
<div>
<span>{{ errors.first('emailAddress') }}</span>
</div>
<div>
<input v-model="customEmail" v-validate="'required|custom-email'" name="customEmailAddress" type="text">
</div>
<div>
<span>{{ errors.first('customEmailAddress') }}</span>
</div>
</div>
</template>

<script>
import validator from '../validators/email';

validator();

const data = function() {
return {
email: '',
customEmail: '',
};
};

export default {
name: 'demo',
data,
};
</script>

19 行

1
2
3
import validator from '../validators/email';

validator();

原本要在 demo component 所跑的 VeeValidate 設定程式,完全整合到 validator() 內。

Validator


email.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import Vue from 'vue';
import VeeValidate, { Validator } from 'vee-validate';
import zhTW from 'vee-validate/dist/locale/zh_TW';
import { config } from './config/config';
import { required, email } from './config/dictionary';
import { emailAddress, customEmailAddress } from './config/attribute';
import customEmailRule from './rules/custom-email';

const dictionary = {
zh_TW: {
messages: {
required,
email,
},
attributes: {
emailAddress,
customEmailAddress,
},
},
};

export default () => {
Vue.use(VeeValidate, config);
Validator.localize('zh_TW', zhTW);
Validator.localize(dictionary);
Validator.extend('custom-email', customEmailRule);
};

第 4 行

1
import { config } from './config/config';

config 目錄下的 VeeValidate 設定檔 import 進來。

第 5 行

1
import { required, email } from './config/dictionary';

config 目錄下 dictionaryrequiredemail 兩個 自訂訊息 import 進來。

第 6 行

1
import { emailAddress, customEmailAddress } from './config/attribute';

config 目錄下 attributeemailAddresscustomEmailAddress 兩個 欄位對照 import 進來。

第 7 行

1
import customEmailRule from './rules/custom-email';

rules 目錄下所需要的 自訂驗證規則檔 import 進來。

第 9 行

1
2
3
4
5
6
7
8
9
10
11
12
const dictionary = {
zh_TW: {
messages: {
required,
email,
},
attributes: {
emailAddress,
customEmailAddress,
},
},
};

定義 VeeValidate 自訂訊息 所需要的 dictionary object。

第一層的 zh_TW語系

第二層的 messages 專門設定 自訂訊息,而 attributes 則設定 欄位對照

23 行

1
2
3
4
Vue.use(VeeValidate, config);
Validator.localize('zh_TW', zhTW);
Validator.localize(dictionary);
Validator.extend('custom-email', customEmailRule);

先使用 localize() 設定 語系,再使用 localize() 設定 dictionary object,這個順序非常重要。

最後使用 extend() 設定 自訂驗證規則

Attribute


attribute.js

1
2
export const emailAddress = '電子郵件';
export const customEmailAddress = '電子郵件';

設定 欄位對照

Config


config.js

1
2
3
4
5
6
7
8
9
export const config = {
errorBagName: 'errors',
fieldsBagName: 'fields',
delay: 100,
strict: true,
enableAutoClasses: true,
inject: true,
events: 'input|blur',
};

統一設定 VeeValidate ,會在 Vue.use(VeeValidate, config); 以第 2 個參數傳入。

Dictionary


dictionary.js

1
2
export const email = field => `${field}格式錯誤`;
export const required = field => `請輸入${field}`;

設定 自訂訊息

Rule


custom-email.js

1
2
3
4
5
6
7
8
9
10
11
const getMessage = field => `${field} 格式不正確`;

const validate = value => {
const regex = /^\w+\.*\w+@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]+$/;
return regex.test(value);
};

export const customEmailRule = {
getMessage,
validate,
};

設定 customEmail 的自訂驗證規則。

Conclusion


  • 由於將 attributredictionaryrule 獨立出來,component 的 validator 可以自由組合所需要的 attributedictionaryrule,非常靈活
  • 當然可以將 VeeValidate 所有的 自訂訊息檔自訂驗證規則檔 統一寫在一起,但這樣子Webpack 的 Tree Shaking 無法發揮,比較好的方式是每個 component 有自己的 validator,再由 validator 架構出所需要的 自訂訊息檔自訂驗證規則檔

Sample Code


完整的範例可以在我的 GitHub 上找到

2018-11-08