cbvirtua 1.0.62 → 1.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
vue自定义指令v-input:限制输入框只能输入数字、字母、中文等规则【附源码】
|
|
2
|
+
指令封装
|
|
3
|
+
directives/input/index.js
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
限制输入框只能输入数字、字母、中文等规则
|
|
7
|
+
|
|
8
|
+
使用指令:v-input
|
|
9
|
+
|
|
10
|
+
修饰符参数说明:
|
|
11
|
+
v-input.num 只能输入数字,默认不传修饰符,会自动限制只能输入数字
|
|
12
|
+
v-input.intp 只能输入正整数
|
|
13
|
+
v-input.num_alp 只能输入数字和字母
|
|
14
|
+
v-input.num_alp_blank 只能输入数字、字母、空格
|
|
15
|
+
v-input.num_alp_sym 只能输入数字和字母、英文符号、空格
|
|
16
|
+
v-input.float 只能输入数字和小数点 v-input.float="2" 表示小数位数为2,默认小数位数为2,v-input.float="2"可以简写为v-input.float
|
|
17
|
+
v-input.no_emoji 不能输入表情符号
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
// 只能输入数字
|
|
21
|
+
function num(el) {
|
|
22
|
+
el.value = el.value.replace(/\D+/g, '')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 只能输入正整数
|
|
26
|
+
function intp(el) {
|
|
27
|
+
const value = el.value.replace(/\D+/g, '') // 去掉非数字字符
|
|
28
|
+
el.value = /^[1-9][0-9]*$/.test(value) ? value : value.replace(/^0+/, '') // 确保为正整数,去掉前导零
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 只能输入数字和字母
|
|
32
|
+
function num_alp(el) {
|
|
33
|
+
el.value = el.value.replace(/[^A-Za-z0-9]/g, '')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 只能输入数字、字母、空格
|
|
37
|
+
function num_alp_blank(el) {
|
|
38
|
+
const regex = /[^a-zA-Z0-9 ]/g
|
|
39
|
+
el.value = el.value.replace(regex, '')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 只能输入数字、字母、英文符号、空格
|
|
43
|
+
function num_alp_sym(el) {
|
|
44
|
+
const regex = /[^a-zA-Z0-9`~!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]/g
|
|
45
|
+
el.value = el.value.replace(regex, '')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 只能输入数字和小数点,n表示小数位数
|
|
49
|
+
function float(el, n) {
|
|
50
|
+
let value = el.value
|
|
51
|
+
value = value.replace(/[^\d.]/g, '') // 能数字和小数点
|
|
52
|
+
value = value.replace(/^\./g, '') // 去掉开头的点
|
|
53
|
+
value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.') // 处理多个点的情况
|
|
54
|
+
if (n && Number(n) > 0) {
|
|
55
|
+
const d = new Array(Number(n)).fill('\\d').join('') // 构建正则表达式
|
|
56
|
+
const reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, 'ig')
|
|
57
|
+
value = value.replace(reg, '$1$2.$3') // 限制小数位数
|
|
58
|
+
}
|
|
59
|
+
// if (value && !value.includes('.')) {
|
|
60
|
+
// value = Number(value).toString() // 去掉开头多个0
|
|
61
|
+
// }
|
|
62
|
+
el.value = value
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 限制表情:😀😂❤️🌟🎉🌍🐶☺
|
|
66
|
+
function no_emoji(el) {
|
|
67
|
+
const regex =
|
|
68
|
+
/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E6}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{263A}]+/gu
|
|
69
|
+
el.value = el.value.replace(regex, '')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 这里扩展限制的类型
|
|
73
|
+
const map = { num, intp, num_alp, num_alp_blank, num_alp_sym, float, no_emoji }
|
|
74
|
+
|
|
75
|
+
export default {
|
|
76
|
+
bind(el, binding, vnode) {
|
|
77
|
+
el = el.querySelector('.el-input__inner') || el.querySelector('.el-textarea__inner') || el
|
|
78
|
+
let lock = false // 标记是否需要锁定输入框
|
|
79
|
+
let isHandling = false // 标记是否正在处理
|
|
80
|
+
let lastValue = null
|
|
81
|
+
// input事件处理函数
|
|
82
|
+
const handler = () => {
|
|
83
|
+
if (lock) return // 如果当前为锁定状态,则不进行处理
|
|
84
|
+
if (isHandling) return // 如果已经在处理中,则不进行处理
|
|
85
|
+
if (el.value === lastValue) return // 输入内容没有变化,则不进行处理
|
|
86
|
+
isHandling = true // 设置标记为处理中
|
|
87
|
+
const modifiers = Object.keys(binding.modifiers)
|
|
88
|
+
const newModifier = modifiers[0] || 'num'
|
|
89
|
+
map[newModifier](el, binding.value || 2)
|
|
90
|
+
lastValue = el.value // 记录当前输入框的值
|
|
91
|
+
Promise.resolve().then(() => {
|
|
92
|
+
// 异步处理,场景:火狐浏览器中,需要在最后派发input事件
|
|
93
|
+
el.dispatchEvent(new Event('input'))
|
|
94
|
+
})
|
|
95
|
+
isHandling = false // 处理完毕后设置标记为非处理状态
|
|
96
|
+
}
|
|
97
|
+
el.addEventListener('input', handler)
|
|
98
|
+
// compositionstart和compositionend事件解决的bug场景:限制只能输入数字的输入框,先输入数字,再切换为中文输入法,输入字母时,会将原来的数字删掉
|
|
99
|
+
el.addEventListener('compositionstart', () => {
|
|
100
|
+
lock = true
|
|
101
|
+
})
|
|
102
|
+
el.addEventListener('compositionend', () => {
|
|
103
|
+
lock = false
|
|
104
|
+
el.dispatchEvent(new Event('input'))
|
|
105
|
+
})
|
|
106
|
+
// 当指令与元素解绑时,移除事件监听器
|
|
107
|
+
vnode.context.$once('hook:destroyed', () => {
|
|
108
|
+
el.removeEventListener('input', handler)
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
directives/index.js
|
|
114
|
+
|
|
115
|
+
import input from './input'
|
|
116
|
+
|
|
117
|
+
const directives = { input }
|
|
118
|
+
|
|
119
|
+
Object.keys(directives).forEach(key => {
|
|
120
|
+
Vue.directive(key, directives[key])
|
|
121
|
+
})
|
|
122
|
+
main.js
|
|
123
|
+
|
|
124
|
+
import './directives'
|
|
125
|
+
注意事项:
|
|
126
|
+
指令的封装不要用keyup事件,当限制只能输入数字时,中文输入法下,输入字母,鼠标点击输入法提示的中文,会将中文输入至文本框中,原因是鼠标点击事件不会触发keyup,用input事件会规避掉这个问题
|
|
127
|
+
使用input事件时,控制台会提示堆栈溢出,需要借助isHandling,执行handler时,先判断是否需要处理
|
|
128
|
+
当限制只能输入数字时,先输入数字,在切换为中文输入法,输入字母时,会将原来的数字删掉,这个问题可以借助compositionstart和compositionend事件解决
|
|
129
|
+
使用
|
|
130
|
+
image.png
|
|
131
|
+
|
|
132
|
+
组件封装
|
|
133
|
+
CustomInput/index.vue
|
|
134
|
+
|
|
135
|
+
<!--
|
|
136
|
+
使用时,直接用 <CustomInput /> 替代 <el-input />
|
|
137
|
+
|
|
138
|
+
limit:限制输入类型,可选值:num、intp、numAlp、numAlpBlank、numAlpSym、float、noEmoji,默认为num
|
|
139
|
+
decimals:当limit为float类型时,限制小数位数
|
|
140
|
+
|
|
141
|
+
支持插槽:
|
|
142
|
+
<CustomInput v-model="subItem.regionHigh" limit="float" maxlength="12" placeholder="请输入" clearable>
|
|
143
|
+
<template slot="prepend">H</template>
|
|
144
|
+
<template slot="append">cm</template>
|
|
145
|
+
</CustomInput>
|
|
146
|
+
|
|
147
|
+
支持拓展:
|
|
148
|
+
1. 定义限制类型的函数
|
|
149
|
+
2. 在map对象中添加此类型
|
|
150
|
+
3. 完善新类型的注释
|
|
151
|
+
-->
|
|
152
|
+
|
|
153
|
+
<template>
|
|
154
|
+
<el-input v-model="inputValue" v-bind="$attrs" v-on="$listeners" @input="handleInput">
|
|
155
|
+
<span v-for="{ name, text } of slotList" :slot="name" :key="text">{{ text }}</span>
|
|
156
|
+
</el-input>
|
|
157
|
+
</template>
|
|
158
|
+
|
|
159
|
+
<script>
|
|
160
|
+
const map = {
|
|
161
|
+
num,
|
|
162
|
+
intp,
|
|
163
|
+
numAlp,
|
|
164
|
+
numAlpBlank,
|
|
165
|
+
numAlpSym,
|
|
166
|
+
float,
|
|
167
|
+
noEmoji
|
|
168
|
+
}
|
|
169
|
+
export default {
|
|
170
|
+
name: 'CustomInput',
|
|
171
|
+
model: { prop: 'value', event: 'changeValue' },
|
|
172
|
+
props: {
|
|
173
|
+
value: { type: [String, Number], default: '' },
|
|
174
|
+
limit: { type: String, default: 'num' }, // 限制输入类型,可选值:num、intp、numAlp、numAlpBlank、numAlpSym、float、noEmoji,默认为num
|
|
175
|
+
decimals: { type: Number, default: 2 } // float类型限制小数位数
|
|
176
|
+
},
|
|
177
|
+
data() {
|
|
178
|
+
const { value } = this
|
|
179
|
+
return { inputValue: value || value === 0 ? String(value) : '', slotList: [] }
|
|
180
|
+
},
|
|
181
|
+
watch: {
|
|
182
|
+
// 手动设置value时,触发handleInput,将不符合限制的字符过滤掉
|
|
183
|
+
value: {
|
|
184
|
+
handler(val) {
|
|
185
|
+
this.handleInput(String(val))
|
|
186
|
+
},
|
|
187
|
+
immediate: true
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
created() {
|
|
191
|
+
this.initSlot()
|
|
192
|
+
},
|
|
193
|
+
methods: {
|
|
194
|
+
handleInput(val) {
|
|
195
|
+
if (!this.limit) return
|
|
196
|
+
const filteredInput = map[this.limit](val, this.decimals)
|
|
197
|
+
this.$emit('changeValue', filteredInput)
|
|
198
|
+
this.inputValue = filteredInput
|
|
199
|
+
},
|
|
200
|
+
initSlot() {
|
|
201
|
+
this.$nextTick(() => {
|
|
202
|
+
const { prepend = [], append = [] } = this.$slots
|
|
203
|
+
const prependList = prepend.map((item) => ({ name: 'prepend', text: item.text }))
|
|
204
|
+
const appendList = append.map((item) => ({ name: 'append', text: item.text }))
|
|
205
|
+
const slotList = prependList.concat(appendList)
|
|
206
|
+
this.slotList = slotList
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// 只能输入数字
|
|
212
|
+
function num(val) {
|
|
213
|
+
const newVal = val.replace(/[^0-9]/g, '')
|
|
214
|
+
return newVal
|
|
215
|
+
}
|
|
216
|
+
// 只能输入正整数
|
|
217
|
+
function intp(val) {
|
|
218
|
+
let newVal = val.replace(/[^0-9]/g, '') // 去掉非数字字符
|
|
219
|
+
newVal = /^[1-9][0-9]*$/.test(newVal) ? newVal : newVal.replace(/^0+/, '') // 确保为正整数,去掉前导零
|
|
220
|
+
return newVal
|
|
221
|
+
}
|
|
222
|
+
// 只能输入数字和字母
|
|
223
|
+
function numAlp(val) {
|
|
224
|
+
const newVal = val.replace(/[^A-Za-z0-9]/g, '')
|
|
225
|
+
return newVal
|
|
226
|
+
}
|
|
227
|
+
// 只能输入数字、字母、空格
|
|
228
|
+
function numAlpBlank(val) {
|
|
229
|
+
const newVal = val.replace(/[^a-zA-Z0-9 ]/g, '')
|
|
230
|
+
return newVal
|
|
231
|
+
}
|
|
232
|
+
// 只能输入数字、字母、英文符号、空格
|
|
233
|
+
function numAlpSym(val) {
|
|
234
|
+
const regex = /[^a-zA-Z0-9`~!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]/g
|
|
235
|
+
const newVal = val.replace(regex, '')
|
|
236
|
+
return newVal
|
|
237
|
+
}
|
|
238
|
+
// 只能输入数字和小数点,n表示小数位数
|
|
239
|
+
function float(val, n) {
|
|
240
|
+
let newVal = val.replace(/[^\d.]/g, '') // 能数字和小数点
|
|
241
|
+
newVal = newVal.replace(/^\./g, '') // 去掉开头的点
|
|
242
|
+
newVal = newVal.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.') // 处理多个点的情况
|
|
243
|
+
if (n && Number(n) > 0) {
|
|
244
|
+
const d = new Array(Number(n)).fill('\\d').join('') // 构建正则表达式
|
|
245
|
+
const reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, 'ig')
|
|
246
|
+
newVal = newVal.replace(reg, '$1$2.$3') // 限制小数位数
|
|
247
|
+
}
|
|
248
|
+
if (newVal && !newVal.includes('.')) {
|
|
249
|
+
// value = value.replace(/^0+/, '')
|
|
250
|
+
// value = Number(value).toString() // 去掉开头多个0
|
|
251
|
+
}
|
|
252
|
+
return newVal
|
|
253
|
+
}
|
|
254
|
+
// 限制不可输入表情
|
|
255
|
+
function noEmoji(val) {
|
|
256
|
+
// 限制表情:😀😂❤️🌟🎉🌍🐶☺
|
|
257
|
+
const regex = /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E6}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{263A}]+/gu
|
|
258
|
+
const newVal = val.replace(regex, '')
|
|
259
|
+
return newVal
|
|
260
|
+
}
|
|
261
|
+
</script>
|
|
262
|
+
|
|
263
|
+
注意事项
|
|
264
|
+
使用时需要传入limit,限制类型;当limit为float时,需要传入decimals,限制小数位数
|
|
265
|
+
支持插槽
|
|
266
|
+
使用
|
|
267
|
+
image.png
|
|
268
|
+
|
|
269
|
+
源码
|
|
270
|
+
www.npmjs.com/package/xtt…
|
|
271
|
+
|
|
272
|
+
/xtt-tools/directives-v2/input/index.js
|