基于ElementUI input 实现IPinput

实现效果
在这里插入图片描述
代码:

<template>
  <div
    :class="['ip-input-container', 'input240', disabled && 'is-disabled']"
    @paste="handlePaste"
  >
    <span v-for="(item, index) in list" :key="index" class="item">
      <el-input
        :ref="`input${index}`"
        v-model="item.val"
        :disabled="disabled"
        :placeholder="item.placeholder"
        :tabindex="`${index}`"
        :maxlength="3"
        @keyup.native="handleKeyup($event, index)"
      />
    </span>
  </div>
</template>

<script>
export default {
  name: 'IpInput',
  props: {
    disabled: {
      type: Boolean,
      default: false
    },
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      list: this.createInputList()
    }
  },
  watch: {
    value() {
      this.dealVal()
    }
  },
  mounted() {
    this.dealVal()
  },
  methods: {
    dealVal() {
      const val = this.value.split('.')
        .filter(item => item !== '')
      this.list.map((item, index) => {
        item.val = val[index] || ''
      })
    },
    handlePaste(ev) {
      const clipTexts = ev.clipboardData.getData('Text')
      const data = clipTexts.split('.')
      const tabIndex = ev.target.tabIndex

      setTimeout(() => {
        const len = this.list.length
        for (let i = 0; i < len; i++) {
          if (data.length === len) {
            this.list[i].val = data[i] || ''
          } else {
            if (i < tabIndex) {
              continue
            }
            this.list[i].val = data[i - tabIndex] || ''
          }
        }
      }, 0)
    },
    handleKeyup(ev, index) {
      const keyCode = ev.keyCode
      // 只能填数字
      ev.target.value = ev.target.value.replace(/[^\d]/g, '')

      // 满3个或者按空格/回车/英文点 跳到下一格
      index < this.list.length - 1 && (this.list[index].val.length === 3 || [32, 13, 190].includes(keyCode)) && this.$refs[`input${index + 1}`][0].focus()

      // 按回退键
      keyCode === 8 && this.list[index].val.length === 0 && index >= 1 && this.$refs[`input${index - 1}`][0].focus()

      const val = this.list
        .map(item => item.val.replace(/[^\d]/g, ''))
        .filter(item => item !== '')
        .join('.')
      this.$emit('input', val)
    },
    createInputList() {
      const arr = []
      for (let i = 0; i < 4; i++) {
        arr.push({ val: '', placeholder: '0' })
      }
      return arr
    }
  }
}
</script>

<style lang="scss" scoped>
  @import "@/styles/theme/_variables";

  .ip-input-container {
    display: flex;
    line-height: 30px;
    border: 1px solid $--base-border-color;
    border-radius: 2px;
    transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);

    &:hover,
    &:focus,
    &:focus-within {
      border: 1px solid $--primary-hover-color;
    }

    &.is-disabled {
      border-color: $--disabled-border-color;
    }

    span.item {
      position: relative;

      ::v-deep {
        .el-input__inner {
          height: 30px;
          padding: 0 12px;
          line-height: 30px;
          border: 0;
        }
      }

      &::after {
        position: absolute;
        left: 0;
        width: 2px;
        height: 2px;
        color: $--base-placeholder-color;
        content: '·';
      }

      &:first-of-type {
        &::after {
          content: '';
        }
      }
    }
  }

  .is-error {
    .ip-input-container {
      border-color: $--danger-color;
    }
  }
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值