vue针对el-input和普通input,尝试写一个清除前后空格或者所有空格的自定义指令

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"
        />
1 Like