github地址: https://github.com/lxmghct/my-vue-components

组件介绍

  • props:
    • value: 输入的ip地址, 类型为字符串, 格式为xx.xx.xx.xx, default: ''
    • disabled: 是否禁用, 类型为布尔值, default: false
  • events:
    • @input: 输入时触发, 参数1为输入的ip地址, 参数2为当前输入的ip的第index段
    • @change: ip地址改变时触发, 参数1为newIp, 参数2为oldIp

效果展示

设计思路

组件设计上比较简单,四个输入框,每个输入框只能输入0-255的数字,输入满3位后自动跳转到下一个输入框,退格Backspace则可以删除内容并跳转到上一个输入框,左右方向键也可以进行切换输入框,这些都只需调用目标输入框的focus()方法即可。

<div class="ip-input">
  <!-- 每一段一个输入框 -->
  <div v-for="(item, index) in ipArr" :key="index" class="ip-input__item-wrap">
    <input
      ref="ipInput"
      v-model="ipArr[index]"
      type="text"
      class="ip-input__item"
      :class="{
        'ip-input__item--active': index === activeIndex,
      }"
      :disabled="disabled"
      @input="handleInput(index)"
      @focus="handleFocus(index)"
      @blur="handleBlur(index)"
      @keydown.left.exact="handleFocus(index - 1)"
      @keydown.right.exact="handleFocus(index + 1)"
      @keydown.backspace.exact="handleBackspace(index)"
    >
    <span v-if="index !== ipArr.length - 1" class="ip-input__dot">.</span>
  </div>
</div>
handleInput(index) {
  const newValue = this.ipArr[index]
  // 如果输入的是非数字,或者输入不在0-255之间,则阻止输入
  if (!this.isNumberValid(newValue)) {
    this.ipArr[index] = this.oldIpInput[index]
    return false
  }
  this.$emit('input', this.ipArr.join('.'), index)
  this.oldIpInput[index] = newValue
  if (newValue.length === 3 || (newValue.length === 2 && newValue > 25)) {
    if (index === this.ipArr.length - 1) { return true }
    // 将焦点移动到下一个输入框
    this.handleFocus(index + 1)
  }
  return true
},
handleFocus(index) {
  if (index < 0 || index > this.ipArr.length - 1) { return }
  if (this.activeIndex !== index) {
    this.$refs.ipInput[index].focus()
  }
  this.activeIndex = index
}

此外,还加入了复制和粘贴ip的功能,粘贴时会自动将ip地址分割并填入到对应的输入框中,复制时会将完整的ip地址复制到剪贴板中。这可以通过监听copypaste事件来实现,通过event.clipboardData来获取剪贴板中的数据。

this.pasteListener = (event)=> {
  if (this.activeIndex === -1) { return }
  const clipboardData = event.clipboardData || window.clipboardData
  this.clipboardText = clipboardData.getData('text')
  this.handlePaste(this.activeIndex)
}
this.copyListener = (event) =>{
  if (this.activeIndex === -1) { return }
  const clipboardData = event.clipboardData || window.clipboardData
  clipboardData.setData('text', this.ipArr.join('.'))
  event.preventDefault()
}
window.addEventListene('paste', this.pasteListener)
window.addEventListene('copy', this.copyListener)

完整代码可以前往文章开头的github地址查看。