wujingjing
2024-04-22 f106e4dffb8279cb90726e83e7edd631f4c77699
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import type { App } from 'vue';
/**
 * @fileoverview 输入限制
 * 使用方法见 vue-input-directive{@link https://github.com/MaiYaoqiang/vue-input-directive}
 * @author wujingjing <gersonwu@qq.com>
 */
 
const trigger = (el, type) => {
    const e = document.createEvent('HTMLEvents');
    e.initEvent(type, true, true);
    el.dispatchEvent(e);
};
const compositionstart = (e) => {
    e.target.composing = true;
};
const compositionend = (e) => {
    e.target.composing = false;
    trigger(e.target, 'input');
};
let initId = 0;
// 生成绑定方法
const getBindFun = function (handler) {
    const id = initId++;
    const bindFun = (el, binding) => {
        const ele = el.tagName === 'INPUT' ? el : el.querySelector('input');
        // 把一些信息存起来 用于判断是否需要重新绑定事件
        // 因为每次输入的时候都会触发指令的update 重复绑定没意义
        if (!ele[id]) {
            ele[id] = {
                oldCallback: null,
                oldValue: null,
            };
        }
        const oldData = ele[id];
        const value = (binding.value && binding.value.toString()) || undefined;
        if (oldData.oldValue !== value) {
            oldData.oldValue = value;
            if (oldData.oldCallback) {
                ele.removeEventListener('keyup', oldData.oldCallback);
                ele.removeEventListener('blur', oldData.oldCallback);
                ele.removeEventListener('compositionstart', compositionstart);
                ele.removeEventListener('compositionend', compositionend);
            }
            const callback = (e) => {
                if (!e.target.composing) {
                    handler(ele, binding);
                    // 不加Trigger会导致输入完 blur后数据变化
                    trigger(ele, 'input');
                }
            };
            ele.addEventListener('keyup', callback);
            ele.addEventListener('blur', callback);
            ele.addEventListener('compositionstart', compositionstart);
            ele.addEventListener('compositionend', compositionend);
            oldData.oldCallback = callback;
        }
    };
    return bindFun;
};
// 生成对应指令需要的生命周期的列表
const getBindListFun = function (bindFun) {
    return {
        mounted: bindFun,
        updated: bindFun,
        inserted: bindFun,
        update: bindFun,
    };
};
// 生成指令对象方法
const DInitFun = function (handler) {
    const bindFun = getBindFun(handler);
    return getBindListFun(bindFun);
};
 
// 输入数字限制最大值
/**
   * @example
   <el-input
   v-d-input-max="99.99"
   v-model="value"></el-input>
   */
const DInputMax = (ele, binding) => {
    let value = ele.value + '';
    if (parseFloat(value) > parseFloat(binding.value)) {
        value = binding.value;
    }
    ele.value = value;
};
 
// 输入数字限制最小值
/**
   * @example
   <el-input
   v-d-input-min="99.99"
   v-model="value"></el-input>
   */
const DInputMin = (ele, binding) => {
    let value = ele.value + '';
    if (parseFloat(value) < parseFloat(binding.value)) {
        value = binding.value;
    }
    ele.value = value;
};
 
/**
   * @example
   <el-input
   v-d-input-int
   v-d-input-max="9999"
   v-model="value"></el-input>
   */
// 只能输入正整数
const DInputInt = (ele, binding) => {
    let value = ele.value + '';
    const reg = /[1-9]{1}\d*/;
    const matchRes = value.match(reg);
    if (matchRes) {
        value = matchRes[0];
    } else {
        value = '';
    }
    ele.value = value;
};
 
/**
 * 精确到指定位数小数
   * @example
   <el-input
   v-d-input-point
   v-d-input-max="99.99"
   v-model="value"></el-input>
   */
const DInputPoint = (ele, binding) => {
    // 精确到几位小数,默认是 2 位
    const decimalPrecision = binding.value ?? 2;
    let value = ele.value + '';
 
    const reg = new RegExp(`^(([1-9][0-9]*)|(([0].d{1,${decimalPrecision}}|[1-9][0-9]*.d{1,${decimalPrecision}})))$`);
    const regSome = new RegExp(`[0-9]+.?[0-9]{0,${decimalPrecision}}`);
    const matchRes = value.match(reg);
    if (matchRes) {
        // 符合 不需要做删减操作
    } else {
        // 若不符合 看是否符合部分
        const matchResSome = value.match(regSome);
        if (matchResSome) {
            value = matchResSome[0];
        } else {
            value = '';
        }
    }
    ele.value = value;
};
 
// 只能输入英文 大小写
const DInputEn = (ele, binding) => {
    let value = ele.value + '';
    const reg = /[a-zA-Z]*/;
    const matchRes = value.match(reg);
    if (matchRes) {
        value = matchRes[0];
    } else {
        value = '';
    }
    ele.value = value;
};
 
/**
   * @example
   <el-input
   v-d-input-regexp="/[0-9]{0,18}/"
   v-model="value"></el-input>
   */
// 限制不能输入中文v-d-input-regexp="/((?![\u4E00-\u9FA5]).)*/"
// 仅可输入数字字母v-d-input-regexp="/[0-9A-Za-z]*/"
const DInputRegexp = (ele, binding) => {
    let value = ele.value + '';
    const reg = binding.value;
    const matchRes = value.match(reg);
    if (matchRes) {
        value = matchRes[0];
    } else {
        value = '';
    }
    ele.value = value;
};
 
const inputMax = DInitFun(DInputMax);
const inputMin = DInitFun(DInputMin);
const inputInt = DInitFun(DInputInt);
const inputPoint = DInitFun(DInputPoint);
const inputEn = DInitFun(DInputEn);
const inputRegexp = DInitFun(DInputRegexp);
export const inputLimit = (app: App) => {
    app.directive('d-input-max', inputMax);
    app.directive('d-input-min', inputMin);
    app.directive('d-input-int', inputInt);
    app.directive('d-input-point', inputPoint);
    app.directive('d-input-en', inputEn);
    app.directive('d-input-regexp', inputRegexp);
};