1、问题的出现
在我司管理端用户的使用过程中,用户反应在使用某个页面的列表查询功能时,查询到的数据不准确,后面经过排查,原来是用户复制粘贴筛选条件的时候带入了空格导致数据不准确。于是决定写一个清除空格的vue自定义指令。
2、设计思路
- 监听input来对input的值进行去空格的处理
- 监听paste处理粘贴动作
- 根据光标位置动态拼接
- 兼顾鼠标选中文字的情况
- 支持el-input和普通input
3、代码
// cleanSpace.js
const ARG_KEY = {
TRIM: 'trim'
}
export default {
bind(el, binding, vnode) {
const componentInstance = vnode.componentInstance // input 为undefined
// input & el-input
// el-input -> 取componentInstance.$refs.input
// input componentInstance是undefined -> 取el
const input = componentInstance ? componentInstance.$refs.input : el
const originInput = input.oninput
input.oninput = function(e) {
const originValue = input.value
// 去除首尾空格
if (binding.arg === ARG_KEY.TRIM) {
e.target.value = e.target.value.trim()
} else {
e.target.value = e.target.value.replace(/ /g, '')
}
if (originInput) {
originInput.call(this, e)
}
// 输入空格这些导致差异才去触发input 的事件
if (originValue !== e.target.value) {
if (!componentInstance) {
const event = new Event('input')
input.dispatchEvent(event)
} else {
// 手动触发 el-input内部事件
componentInstance.handleInput(e)
}
}
}
input.onpaste = function(e) {
let text = ''
// 选中的文字
let selectText = window.getSelection().toString()
const selectionStart = e.target.selectionStart
const originValue = input.value
if (window.clipboardData && window.clipboardData.getData) {
text = window.clipboardData.getData('Text')
} else {
text = e.clipboardData.getData('Text')
}
// 去除首尾空格
if (binding.arg === ARG_KEY.TRIM) {
text = text.trim()
} else {
text = text.replace(/ /g, '')
}
const startText = originValue.substring(0, selectionStart)
let endText = originValue.substring(selectionStart, originValue.length)
// 选中的文字要替换了
if (selectText) {
endText = endText.substring(selectText.length, endText.length)
}
if (e.target.maxLength && e.target.maxLength > 0) {
input.value = (startText + text + endText).substring(
0,
e.target.maxLength
)
} else {
input.value = startText + text + endText
}
// 输入空格这些导致差异才去触发input 的事件
if (originValue !== e.target.value) {
if (!componentInstance) {
const event = new Event('input')
input.dispatchEvent(event)
} else {
// 手动触发 el-input内部事件
componentInstance.handleInput(e)
}
}
return false
}
}
}
// index.js
import cleanSpace from './cleanSpace'
const install = function(Vue) {
Vue.directive('cleanSpace', cleanSpace)
}
cleanSpace.install = install
export default cleanSpace
4、使用方式
// main.js
import cleanSpace from '@/xxx/cleanSpace/index' // 清除空格指令
Vue.use(cleanSpace)
// 去除前后空格
<el-input
v-clean-space:trim
v-model="name"
@keyup.enter.native="handle"
/>
// 去除所有空格
<el-input
v-clean-space
v-model="name"
@keyup.enter.native="handle"
/>
// 普通input
<input
v-clean-space
v-model="name"
/>