├── .npmignore
├── .gitignore
├── tsconfig.json
├── src
├── types.ts
├── error-message-template.ts
├── rules.ts
├── error-message.ts
├── component.ts
└── index.ts
├── README.md
├── package.json
└── yarn.lock
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | node_modules
3 | .idea
4 | dist
5 | types
6 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "strict": true,
4 | "moduleResolution": "node",
5 | "target": "ES5",
6 | "lib": ["dom", "es6"],
7 | "experimentalDecorators": true,
8 | "emitDecoratorMetadata": true,
9 | "declaration": true,
10 | "declarationDir": "./types/",
11 | "outDir": "./dist"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | export type RuleGetter = (ruleVal?: any) => object;
2 | export type ErrorMessageTemplate = {
3 | empty: string;
4 | length: string;
5 | minLength: string;
6 | number: string;
7 | int: string;
8 | lt: string;
9 | lte: string;
10 | gt: string;
11 | gte: string;
12 | maxDecimalLength: string;
13 | phone: string;
14 | email: string;
15 | verifyCode: string;
16 | [name: string]: string;
17 | };
18 |
--------------------------------------------------------------------------------
/src/error-message-template.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | empty: "请补充该项内容",
3 | length: "请输入{length}位字符",
4 | minLength: "输入内容至少{minLength}位",
5 | number: "请输入数字",
6 | int: "请输入整数",
7 | lt: "输入内容应小于{lt}",
8 | lte: "输入内容不能大于{lte}",
9 | gt: "输入内容应大于{gt}",
10 | gte: "输入内容不能小于{gte}",
11 | maxDecimalLength: "该输入项最多接受{maxDecimalLength}位小数",
12 | phone: "请输入正确的手机号",
13 | email: "请输入正确的邮箱",
14 | verifyCode: "请输入正确的验证码"
15 | };
16 |
--------------------------------------------------------------------------------
/src/rules.ts:
--------------------------------------------------------------------------------
1 | import { RuleGetter } from "./types";
2 | export type RuleGetters = { [name: string]: RuleGetter };
3 | const getters: RuleGetters = {};
4 | function rules(): RuleGetters;
5 | function rules(name: string, getter?: RuleGetter): RuleGetter;
6 | function rules(name?: string, getter?: RuleGetter): any {
7 | if (!name) return getters;
8 | if (getters[name] && getter)
9 | throw Error(`the rule name '${name}' has been used`);
10 | if (getter) getters[name] = getter;
11 | return getters[name];
12 | }
13 | export default rules;
14 |
--------------------------------------------------------------------------------
/src/error-message.ts:
--------------------------------------------------------------------------------
1 | import { ErrorMessageTemplate } from "./types";
2 |
3 | let template: ErrorMessageTemplate;
4 | type MacroMap = { [macro: string]: string };
5 |
6 | function createMacroMap(macro: string, value: any): MacroMap {
7 | const obj: any = {};
8 | obj[macro] = value;
9 | return obj;
10 | }
11 |
12 | export default {
13 | setTemplate(errorMessageTemplate: ErrorMessageTemplate) {
14 | template = errorMessageTemplate;
15 | },
16 | macroToValue(msg: string, macro: string, value: any): string {
17 | const reg = new RegExp(`{${macro}}`, "g");
18 | return msg.replace(reg, value);
19 | },
20 | get(name: string, templateData?: any): string {
21 | let msg = template[name];
22 | if (!msg)
23 | throw Error(`can't get the value of errorMessageTemplate['${name}']`);
24 | if (arguments.length === 1) return msg;
25 | if (typeof templateData !== "object")
26 | templateData = createMacroMap(name, templateData);
27 | for (let macro in templateData)
28 | msg = this.macroToValue(msg, macro, templateData[macro]);
29 | return msg;
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # element-ui-verify
2 |
3 | 如果你受够了饿了么 ElementUI 原生的校验方式,那就来试试它吧!
4 |
5 | ## 前言
6 |
7 | 饿了么 ElementUI 虽好,但表单校验的体验不够理想
8 |
9 | 如果说产品开发要讲究用户体验,那插件开发也要讲究开发体验,而好的开发体验,要靠好的 api 设计来保障
10 |
11 | 本人专注校验插件开发 30 年,有祖传的校验插件 api 设计(玩笑)。主要是参考了之前写的[vue-verify-pop](https://github.com/aweiu/vue-verify-pop)的 api,并加以完善,取其精华,去其糟粕,揉和日月之精华。。。
12 |
13 | 本插件只是对 ElementUI 原本的校验方式做了一层封装,核心的校验器仍然是[async-validator](https://github.com/yiminghe/async-validator),非侵入式,完全不会影响你继续使用 ElementUI 的原生校验
14 |
15 | ## 示例
16 |
17 | ```html
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
36 | ```
37 |
38 | ok,你已经完成了一个内容为大于 0 的整数校验!([欢迎对比官方版的相似例子](http://element-cn.eleme.io/#/zh-CN/component/form#shu-zi-lei-xing-yan-zheng))
39 |
40 | ## 文档
41 |
42 | https://aweiu.com/documents/element-ui-verify/
43 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "element-ui-verify",
3 | "version": "1.2.6",
4 | "description": "如果你受够了饿了么ElementUI原生的校验方式,那就来试试它吧!一款更懂你的校验插件",
5 | "keywords": [
6 | "vue",
7 | "element",
8 | "element-ui",
9 | "elementUi",
10 | "elementUI",
11 | "element-ui-validator",
12 | "element-ui-verification",
13 | "element-ui-check"
14 | ],
15 | "main": "dist/index.js",
16 | "typings": "types/index.d.ts",
17 | "scripts": {
18 | "build": "tsc"
19 | },
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/aweiu/element-ui-verify.git"
23 | },
24 | "author": "aweiu",
25 | "license": "ISC",
26 | "bugs": {
27 | "url": "https://github.com/aweiu/element-ui-verify/issues"
28 | },
29 | "homepage": "https://github.com/aweiu/element-ui-verify#readme",
30 | "dependencies": {
31 | "vue-property-decorator": "^6.0.0"
32 | },
33 | "peerDependencies": {
34 | "element-ui": ">=1.1.1",
35 | "vue": "^2.3.0"
36 | },
37 | "devDependencies": {
38 | "element-ui": "^2.0.10",
39 | "prettier": "^1.18.2",
40 | "typescript": "^2.6.2",
41 | "vue": "^2.5.13"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/component.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import { FormItem } from "element-ui";
3 | import rules from "./rules";
4 | import errorMessage from "./error-message";
5 | import { Component, Prop, Watch } from "vue-property-decorator";
6 |
7 | // 引用一份,解决某些环境下调用了全局Vue.mixin后再调用原FormItem下的方法会造成调用栈溢出
8 | const ElFormItemMethods: { [methodName: string]: Function } = (FormItem as any)
9 | .methods;
10 | @Component
11 | export default class ElFormItemVerifyComponent extends Vue {
12 | static fieldChange: "verify" | "clear";
13 | @Prop([String, Function])
14 | verify?: string | Function;
15 | @Prop()
16 | canBeEmpty?: string;
17 | @Prop()
18 | space?: string;
19 | @Prop()
20 | emptyMessage?: string;
21 | @Prop()
22 | errorMessage?: string;
23 | @Prop()
24 | alias?: string;
25 | @Prop()
26 | watch: undefined;
27 | @Prop()
28 | fieldChange?: string;
29 |
30 | // watch某值并修改该值本身会额外触发一次,性能影响不大,暂不做过滤了。后期可能会用其它方式拦截
31 | @Watch("validateMessage")
32 | onValidateMessageChanged(msg: string) {
33 | if (this._verify && msg !== "") {
34 | const alias = this.alias || (this as any).label || "该输入项";
35 | (this as any).validateMessage = errorMessage.macroToValue(
36 | (this as any).validateMessage,
37 | "alias",
38 | alias
39 | );
40 | }
41 | }
42 |
43 | @Watch("watch")
44 | onWatchChanged() {
45 | if (this._verify) (this as any).validate("");
46 | }
47 |
48 | get _verify(): boolean {
49 | return this.verify !== undefined && (this as any).prop;
50 | }
51 |
52 | getRules(): any[] {
53 | if (!this._verify) return ElFormItemMethods.getRules.apply(this, arguments);
54 | let asyncVerifyRules: any[] = [];
55 | // 空检测
56 | let fieldValue = (this as any).fieldValue;
57 | fieldValue =
58 | [undefined, null].indexOf(fieldValue) === -1 ? fieldValue + "" : "";
59 | if (this.space === undefined) fieldValue = fieldValue.trim();
60 | if (fieldValue === "") {
61 | asyncVerifyRules.push({
62 | validator: (rule: any, val: any, callback: Function) => {
63 | if (this.canBeEmpty !== undefined || (this as any).minLength <= 0)
64 | callback();
65 | else callback(Error(this.emptyMessage || errorMessage.get("empty")));
66 | }
67 | });
68 | } else {
69 | // 合并普通规则
70 | const ruleGetters = rules();
71 | for (let name in ruleGetters) {
72 | const ruleVal = (this as any)[name];
73 | if (ruleVal !== undefined)
74 | asyncVerifyRules = asyncVerifyRules.concat(
75 | ruleGetters[name](ruleVal)
76 | );
77 | }
78 | // 统一处理错误提示(代码块放在此处可以只针对普通规则)
79 | if (this.errorMessage !== undefined) {
80 | for (let rule of asyncVerifyRules)
81 | (rule as any).message = this.errorMessage;
82 | }
83 | // 自定义校验方法置后
84 | if (typeof this.verify === "function")
85 | asyncVerifyRules.push({ validator: this.verify });
86 | // 当规则为空时,返回一个始终通过的规则来避免空检测错误无法清除
87 | // 也可以通过(this as any).clearValidate()的方式实现,不过不太好
88 | if (asyncVerifyRules.length === 0) {
89 | asyncVerifyRules.push({
90 | validator(rule: any, val: any, callback: Function) {
91 | callback();
92 | }
93 | });
94 | }
95 | }
96 | // 使elementUI可以检测到必填项从而展示*号
97 | asyncVerifyRules[0].required = this.canBeEmpty === undefined;
98 | return asyncVerifyRules;
99 | }
100 |
101 | // 兼容<2.0.0-beta.1
102 | clearValidate() {
103 | if (ElFormItemMethods.clearValidate) {
104 | ElFormItemMethods.clearValidate.apply(this, arguments);
105 | } else {
106 | (this as any).validateState = "";
107 | (this as any).validateMessage = "";
108 | (this as any).validateDisabled = false;
109 | }
110 | }
111 |
112 | onFieldChange() {
113 | const fieldChange =
114 | this.fieldChange || ElFormItemVerifyComponent.fieldChange;
115 | if (!this._verify || fieldChange !== "clear")
116 | ElFormItemMethods.onFieldChange.apply(this, arguments);
117 | else if (this._verify && fieldChange === "clear") this.clearValidate();
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | async-validator@~1.8.1:
6 | version "1.8.5"
7 | resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-1.8.5.tgz#dc3e08ec1fd0dddb67e60842f02c0cd1cec6d7f0"
8 | integrity sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==
9 | dependencies:
10 | babel-runtime "6.x"
11 |
12 | babel-helper-vue-jsx-merge-props@^2.0.0:
13 | version "2.0.3"
14 | resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
15 | integrity sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==
16 |
17 | babel-runtime@6.x:
18 | version "6.26.0"
19 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
20 | integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
21 | dependencies:
22 | core-js "^2.4.0"
23 | regenerator-runtime "^0.11.0"
24 |
25 | core-js@^2.4.0:
26 | version "2.6.9"
27 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
28 | integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
29 |
30 | deepmerge@^1.2.0:
31 | version "1.5.2"
32 | resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
33 | integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==
34 |
35 | element-ui@^2.0.10:
36 | version "2.11.1"
37 | resolved "https://registry.yarnpkg.com/element-ui/-/element-ui-2.11.1.tgz#2b67f9eee3eda2e6884873c1c589cbe30d9a9d60"
38 | integrity sha512-PACNMHPWqm+/Wc2f/q93pLNzbNyVbpMCXCrYe81czengSWj7IBku7F3zccybkxtWn5qdCmMDBCpG5BzGJL4rKA==
39 | dependencies:
40 | async-validator "~1.8.1"
41 | babel-helper-vue-jsx-merge-props "^2.0.0"
42 | deepmerge "^1.2.0"
43 | normalize-wheel "^1.0.1"
44 | resize-observer-polyfill "^1.5.0"
45 | throttle-debounce "^1.0.1"
46 |
47 | normalize-wheel@^1.0.1:
48 | version "1.0.1"
49 | resolved "https://registry.yarnpkg.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
50 | integrity sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=
51 |
52 | prettier@^1.18.2:
53 | version "1.18.2"
54 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
55 | integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
56 |
57 | reflect-metadata@^0.1.10:
58 | version "0.1.13"
59 | resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
60 | integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
61 |
62 | regenerator-runtime@^0.11.0:
63 | version "0.11.1"
64 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
65 | integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
66 |
67 | resize-observer-polyfill@^1.5.0:
68 | version "1.5.1"
69 | resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
70 | integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
71 |
72 | throttle-debounce@^1.0.1:
73 | version "1.1.0"
74 | resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz#51853da37be68a155cb6e827b3514a3c422e89cd"
75 | integrity sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==
76 |
77 | typescript@^2.6.2:
78 | version "2.9.2"
79 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
80 | integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==
81 |
82 | vue-class-component@^6.1.0:
83 | version "6.3.2"
84 | resolved "https://registry.yarnpkg.com/vue-class-component/-/vue-class-component-6.3.2.tgz#e6037e84d1df2af3bde4f455e50ca1b9eec02be6"
85 | integrity sha512-cH208IoM+jgZyEf/g7mnFyofwPDJTM/QvBNhYMjqGB8fCsRyTf68rH2ISw/G20tJv+5mIThQ3upKwoL4jLTr1A==
86 |
87 | vue-property-decorator@^6.0.0:
88 | version "6.1.0"
89 | resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-6.1.0.tgz#ef97bcc1bfe794ec060133ca04a5aca02e808828"
90 | integrity sha512-NM4PYPOkOIO7SFtWiQqVrbp+ORzd7CJXcIz0X710PNW9pxGfbil0/x/ULFympzIUoHXBKN2dqoOQzh6oeMzpTQ==
91 | dependencies:
92 | reflect-metadata "^0.1.10"
93 | vue-class-component "^6.1.0"
94 |
95 | vue@^2.5.13:
96 | version "2.6.10"
97 | resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
98 | integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
99 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import rules from "./rules";
2 | import Component from "./component";
3 | import errorMessage from "./error-message";
4 | import defaultErrorMessageTemplate from "./error-message-template";
5 | import { VueConstructor } from "vue";
6 | import { PropOptions } from "vue/types/options";
7 | import { RuleGetter, ErrorMessageTemplate } from "./types";
8 |
9 | export interface VerifyRulePropOptions extends PropOptions {
10 | name: string;
11 | }
12 |
13 | let ElFormItemComponent: VueConstructor;
14 |
15 | function addRule(
16 | name: string | VerifyRulePropOptions,
17 | getter: RuleGetter
18 | ): RuleGetter {
19 | if (!ElFormItemComponent) throw Error("please install me");
20 | const props: any = {};
21 | if (typeof name === "string") props[name] = {};
22 | else props[name.name] = name;
23 | const _name = typeof name === "string" ? name : name.name;
24 | const component: any = { props };
25 | // 监听prop变化,触发校验
26 | component.watch = {};
27 | component.watch[_name] = function() {
28 | if (this.verify !== undefined && (this as any).prop)
29 | (this as any).validate("");
30 | };
31 | ElFormItemComponent.mixin(component);
32 | return rules(_name, getter);
33 | }
34 |
35 | function getRule(name: string): RuleGetter {
36 | return rules(name);
37 | }
38 |
39 | function getErrorMessage(name: string, templateData?: any): string {
40 | return errorMessage.get(name, templateData);
41 | }
42 |
43 | function init() {
44 | const transform = (value: string) => Number(value);
45 | // 文本长度
46 | addRule({ name: "length", type: Number }, length => ({
47 | len: length,
48 | message: getErrorMessage("length", length)
49 | }));
50 | // 最小文本长度
51 | addRule({ name: "minLength", type: Number }, minLength => ({
52 | min: minLength,
53 | message: getErrorMessage("minLength", minLength)
54 | }));
55 | // 数字
56 | addRule("number", () => ({
57 | validator(rule: any, val: string, callback: Function) {
58 | if (/^([-+])?\d+(\.\d+)?$/.test(val)) callback();
59 | else callback(Error(getErrorMessage("number")));
60 | }
61 | }));
62 | // gt
63 | addRule({ name: "gt", type: Number }, gt => [
64 | getRule("number")(),
65 | {
66 | validator(rule: any, val: number, callback: Function) {
67 | if (val > gt) callback();
68 | else callback(Error(getErrorMessage("gt", gt)));
69 | }
70 | }
71 | ]);
72 | // gte
73 | addRule({ name: "gte", type: Number }, gte => [
74 | getRule("number")(),
75 | {
76 | type: "number",
77 | min: gte,
78 | transform,
79 | message: getErrorMessage("gte", gte)
80 | }
81 | ]);
82 | // lt
83 | addRule({ name: "lt", type: Number }, lt => [
84 | getRule("number")(),
85 | {
86 | validator(rule: any, val: number, callback: Function) {
87 | if (val < lt) callback();
88 | else callback(Error(getErrorMessage("lt", lt)));
89 | }
90 | }
91 | ]);
92 | // lte
93 | addRule({ name: "lte", type: Number }, lte => [
94 | getRule("number")(),
95 | {
96 | type: "number",
97 | max: lte,
98 | transform,
99 | message: getErrorMessage("lte", lte)
100 | }
101 | ]);
102 | // 整数类型
103 | addRule("int", () => [
104 | getRule("number")(),
105 | {
106 | type: "integer",
107 | transform,
108 | message: getErrorMessage("int")
109 | }
110 | ]);
111 | // 最多小数位
112 | addRule({ name: "maxDecimalLength", type: Number }, maxDecimalLength => [
113 | getRule("number")(),
114 | {
115 | validator(rule: any, val: string | number, callback: Function) {
116 | const decimal = val.toString().split(".")[1];
117 | if (decimal && decimal.length > maxDecimalLength)
118 | callback(
119 | Error(getErrorMessage("maxDecimalLength", maxDecimalLength))
120 | );
121 | else callback();
122 | }
123 | }
124 | ]);
125 | // 手机号 https://github.com/aweiu/element-ui-verify/issues/24
126 | addRule("phone", () => ({
127 | pattern: /^(?=\d{11}$)^1(?:3\d|4[57]|5[^4\D]|6[67]|7[^249\D]|8\d|9[189])\d{8}$/,
128 | message: getErrorMessage("phone")
129 | }));
130 | // 邮箱
131 | addRule("email", () => ({
132 | type: "email",
133 | message: getErrorMessage("email")
134 | }));
135 | // 6位数字验证码
136 | addRule("verifyCode", () => ({
137 | pattern: /^\d{6}$/,
138 | message: getErrorMessage("verifyCode")
139 | }));
140 | }
141 |
142 | function install(
143 | Vue: VueConstructor,
144 | options: {
145 | errorMessageTemplate?: ErrorMessageTemplate;
146 | fieldChange?: "clear" | "verify";
147 | } = {}
148 | ) {
149 | ElFormItemComponent = Vue.component("ElFormItem");
150 | if (!ElFormItemComponent) throw Error("please install element-ui first");
151 | errorMessage.setTemplate(
152 | options.errorMessageTemplate || defaultErrorMessageTemplate
153 | );
154 | Component.fieldChange = options.fieldChange || "verify";
155 | ElFormItemComponent.mixin(Component);
156 | init();
157 | }
158 |
159 | export default {
160 | install,
161 | addRule,
162 | getRule,
163 | getErrorMessage
164 | };
165 |
--------------------------------------------------------------------------------