表单类的 IP 组件封装二、

由于element-ui  和 iview-ui 组件库,目前暂未提供 IP 类的组件,小编组件封装了一个vue的IP组件,仅供大家使用和学习探讨;

之前也有写有 IP组件的文章,这次是二次优化,

1.优化了之前没输入3位数后自动跑到 下一个空格里面,本次优化后,每输入3位数值后,需要输入  " ."   或者enter键,才会 跳到 下一个空格里面;
2. 优化了,每次调用后,再次点击新增数据的时候, 清空上次的数据

代码如下:

父组件:

            <FormItem label="设备IP:" prop="ip">
              <ip-check v-model="formAddDevice.ip"> </ip-check>
            </FormItem>

import ipCheck from '@/components/ipModal/ipCheck.vue';
components: {'ipCheck': ipCheck},

data(){

    // 设备IP 验证
    const validateip = (rule, value, callback) => {
      if (value === '') {
        return callback(new Error('请输入设备IP!'))
      } else {
        return callback()
      }
    }
    return:{
        formAddDevice: {
            ip: '',
    
        },
        addRules:{
                ip: [
                  { required: true, type: 'string', message: 'IP不能为空!', trigger: 'blur' },
              { validator: validateip, trigger: 'blur' }
            ]
        }
    }
}


子组件代码:

<template>
  <div class="ipAdress">
    <ul id="id1" class="ipInput" :class="{ isDisabled: isDisabled }">
      <li v-for="(item, index) in ipAdress" :key="index">
        <input
          ref="ipInput"
          v-model="item.value"
          :tabindex="'ipInput' + (index + 1)"
          :class="'ipAdress' + (index + 1)"
          autocomplete="off"
          :readonly="isDisabled"
          :maxlength="3"
          type="tel"
          pattern="[0-9]{1,3}"
          :disabled="isDisabled || detailsFlag"
          @blur="blurFocus(index)"
          @input="checkIpVal(item, index, $event)"
          @keyup="turnIpPOS(item, index, $event)"
          @keydown="delteIP(item, index, $event)"
        >
        <span v-if="index < 3">.</span>
      </li>
    </ul>
    <!-- <div class="error">请输入IP地址!</div> -->
  </div>
</template>

<script>
export default {
  model: {
    prop: 'ipStr',
    event: 'change'
  },
  props: {
    ipStr: {
      type: String,
      default: ''
    },
    ipType: {
      type: String,
      default: ''
    },
    isDisabled: {
      type: Boolean,
      default: false
    },
    width: {
      type: String,
      default: '100%'
    }
  },
  data() {
    return {
      title_name: '',
      detailsFlag: false, // 详情页是否:disabled
      erro_ip: true,
      ipAdress: [
        {
          value: ''
        },
        {
          value: ''
        },
        {
          value: ''
        },
        {
          value: ''
        }
      ],

      isWX: navigator.userAgent.toLowerCase().match(/MicroMessenger/i) === 'micromessenger'
    }
  },
  watch: {
    ipStr: {
      immediate: true,
      handler: function(vall) {
        const val = vall
        let nArr = []
        if (val && val.includes('.') && val.length > 0) {
          const valArr = val.split('.')
          const m = valArr.length
          for (let i = 0; i < 4; i++) {
            if (valArr[i] === 'null' || valArr[i] === 'undefined') {
              valArr[i] = ''
            }
            if (i < m) {
              nArr.push({
                value: valArr[i]
              })
            } else {
              nArr.push({
                value: ''
              })
            }
          }
        } else {
          nArr = [{ value: '' }, { value: '' }, { value: '' }, { value: '' }]
        }
        this.ipAdress = nArr
      }
    },
    title_name: function(data) {
      // console.log("title_name:",data)
      if (data.indexOf('详情') !== -1) {
        // 详情
        this.detailsFlag = true
      } else {
        // 新增或者编辑
        this.detailsFlag = false
      }
    }
  },
  destroyed() {
    this.$destroy()
  },
  methods: {
    // methods
    blurFocus(index) {
      if (index === 3) {
        this.$emit('blur')
      }
    },
    checkIpVal(item, index, event) {
      const self = this
      // wx
      if (this.isWX) {
        const e = event || window.event
        const keyCode = e.data

        // .向右跳转
        if (keyCode === '.') {
          e.preventDefault()
          e.returnValue = false
          item.value = item.value.replace(/[^\d]/g, '').replace(/[\.]/g, '')
          if (index < 3) {
            self.$refs.ipInput[index + 1].focus()
          }
          return false
        }
      }

      // const isNo = /^[0-9]{1,3}$/g
      if (/[^\d]/g.test(item.value)) {
        const cache = JSON.parse(JSON.stringify(self.ipAdress))
        cache[index].value = item.value.replace(/[^\d]/g, '').replace(/[\.]/g, '')
        self.ipAdress = cache
        return false
      }

      if (item.value.replace(/[^\d]/g, '').length >= 3) {
        let val = parseInt(item.value.replace(/[^\d]/g, ''), 10)
        if (isNaN(val)) {
          val = ''
        } else if (val > 255) {
          val = 255
        } else {
          val = val < 0 ? 0 : val
        }
        item.value = String(val)
        this.$set(this.ipAdress, index, item)
      }
      let ns = ''
      this.ipAdress.forEach((item) => (ns += '.' + item.value))

      // 给父组件传值 ip的值
      if (true) {
        let ip = ''
        this.ipAdress.map((v) => {
          ip = ip + '.' + v.value
        })
        this.$emit('change', ip.substring(1))
      }
    },
    turnIpPOS(item, index, event) {
      const self = this
      const e = event || window.event

      if (e.keyCode === 37) {
        if (index !== 0) {
          self.$refs.ipInput[index - 1].focus()
        }
      }
      // 右箭头、回车键、空格键、冒号均向右跳转,右一不做任何措施
      if (e.keyCode === 39 || e.keyCode === 13 || e.keyCode === 32 || e.keyCode === 110 || e.keyCode === 46 || e.keyCode === 190) {
        e.preventDefault()
        e.returnValue = false
        if (index < 3) {
          self.$refs.ipInput[index + 1].focus()
        }
        return false
      }
    },
    delteIP(item, index, event) {
      // console.log('deleteIP:',item, index, event)
      const self = this
      const e = event || window.event
      let val = parseInt(item.value.replace(/[^\d]/g, ''), 10)
      val = isNaN(val) ? '' : val
      if (e.keyCode === 8 && index > 0 && val.length === 0) {
        self.$refs.ipInput[index - 1].focus()
      }
    }
  }
}
</script>

<style lang="scss">
.ipAdress {
  position: relative;
  .error {
    position: absolute;
    padding-top: 10px;
    display: inline-block;
    margin: 0%;
    padding: 0%;
    color: #f56c6c;
    line-height: 1;
    font-size: 12px;
  }
}
.ipInput {
  width: 100%;
  height: 29px;
  box-sizing: border-box;
  line-height: inherit;
  border: 1px solid #dcdfe6;
  background-color: #fff;
  overflow: hidden;
  border-radius: 4px;
  padding: 0;
  margin: 0;
  display: inline-block;
  vertical-align: middle;
  outline: transparent;
  font-size: 0;
  text-indent: 0;
  background: #fff;
  display: flex;
  flex-direction: row;
}
.ipInput.isDisabled {
  background: transparent;
}
.ipInput.isDisabled li {
  cursor: not-allowed;
  height: 29px;
}
.ipInput.isDisabled li input {
  cursor: not-allowed;
}
.ipInput li {
  display: inline-block;
  width: 25%;
  height: 29px;
  box-sizing: border-box;
  font-size: 0;
  display: flex;
  flex-direction: row;
}
.ipInput .ivu-input:focus {
  box-shadow: none;
}

.ipInput li input {
  appearance: none;
  padding: 10px 5px;
  width: calc(100% - 3px);
  text-align: center;
  outline: none;
  border: none;
  color: #000;
  box-sizing: border-box;
  font-size: 12px;
  height: 29px;
}
.ipInput li input.disabled {
  background: transparent;
}
.ipInput input:disabled {
  background-color: #f3f3f3;
  opacity: 1;
  cursor: not-allowed;
  color: #ccc;
}
.ipInput li span {
  display: inline-block;
  font-size: 20px;
  width: 4px;
  height: 4px;
  color: #000;
}
</style>

 补充说明:关于子组件参数的表单验证:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT博客技术分享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值