手写IP地址输入框

2023-01-09 20:25:55

1、问题

页面开发的时候,有一个需求是弹窗中使用与 IP 地址相同功能的输入框(弹窗宽度固定),本来想使用 element 的输入框的插槽实现,最后发现行不通,只能手写一个这样的组件了

原型要求:
在这里插入图片描述

2、要求:

  1. 每个 IP 地址框数据长度不能超过三位
  2. 展示上需要用原点分割每一个 IP 地址

3、初步实现

  • 主要使用 element 实现

下列代码实现在一个输入框中插入圆点以分割不同的地址,但是一个输入框只能输入一个数据,添加分割没有太大作用

<!-- 初步实现一个 -->
<el-input v-model="one" ref="one" maxlength="3"></el-input>
<div style="position: absolute;left: 74px;font-size: 20px;">.</div>
  • 实现四个输入框

四个输入框用于模拟类似 IP 地址的输入

<el-input v-model="one" class="ip-address__input" ref="one" maxlength="3"
></el-input>
<div style="position: absolute;left: 74px;font-size: 20px;">.</div>
<el-input class="ip-address__input" v-model="two" ref="two" maxlength="3"
></el-input>
<div style="position: absolute;left: 148px;font-size: 20px;">.</div>
<el-input class="ip-address__input" v-model="three" ref="three" maxlength="3"
></el-input>
<div style="position: absolute;left: 222px;font-size: 20px;">.</div>
<el-input class="ip-address__input" v-model="four" ref="four" maxlength="3"
></el-input>

下面是样式处理:

.ip-address__input {
    .el-input__inner:focus {
      border: 1px solid #DCDFE6;
    }
}
// 调整输入框的边框显示,整合为统一的输入框
.ip-address__input:nth-child(1) {
    .el-input__inner {
      border-right: 0px !important;
      border-radius: 4px 0 0 4px;
    }
}
.ip-address__input:nth-child(3),
.ip-address__input:nth-child(5) {
    .el-input__inner {
      border-right: 0px !important;
      border-left: 0px !important;
      border-radius: 0;
    }
}
.ip-address__input:nth-child(7) {
    .el-input__inner {
      border-radius: 0 4px 4px 0;
      border-left: 0px !important;
    }
}
  • 最后是逻辑处理(略)
    • 输入框的监听
    • 键盘监听

4、完整代码

<template>
  <div class="ip-address">
    <el-input 
      v-model="one" 
      class="ip-address__input" 
      ref="one" 
      @keyup.enter.native="nextFocus('one')"
      maxlength="3"
    ></el-input>
    <div style="position: absolute;left: 74px;font-size: 20px;">
    .
    </div>
    <el-input 
      class="ip-address__input" 
      @keyup.enter.native="nextFocus('two')"
      v-model="two" 
      ref="two" 
      maxlength="3"
    ></el-input>
    <div style="position: absolute;left: 148px;font-size: 20px;">
    .
    </div>
    <el-input 
      class="ip-address__input" 
      @keyup.enter.native="nextFocus('three')"
      v-model="three" 
      ref="three" 
      maxlength="3"
    ></el-input>
    <div style="position: absolute;left: 222px;font-size: 20px;">
    .
    </div>
    <el-input 
      class="ip-address__input" 
      v-model="four" 
      @keyup.enter.native="handleSave('save')"
      ref="four" 
      maxlength="3"
    ></el-input>
  </div>
</template>
<script>
export default {
  data() {
    return {
      one: "",
      two: "",
      three: "",
      four: "",
      ipArr: ['one' , 'two' , 'three' , 'four']
    };
  },
  watch: {
    one(newval) {
      if (newval.length === 3) {
        this.nextFocus('one')
      }
    },
    two(newval) {
      if (newval.length === 3) {
        this.nextFocus('two')
      }
    },
    three(newval) {
      if (newval.length === 3) {
        this.nextFocus('three')
      }
    }
  },
  methods: {
    // 输入框跳转逻辑
    nextFocus(loc) {
      let index = this.ipArr.indexOf(loc) + 1;
      if(index === -1 || index >= this.ipArr.length) return ;
      this.$nextTick( () => {
        this.$refs[this.ipArr[index]].focus();
      })
    },
    // 将地址格式化展示
    setIPValue(ip) {
      console.log("地址:",ip);
      if(!ip) {
        this.ipArr.forEach( v => {this[v] = ""});
        return ;
      }
      [this.one , this.two , this.three , this.four] = [...ip.split(".")];
      // setTimeout( () => { this.$refs.one.focus(); },10)
    },
    // 获取地址
    getIPValue() {  
      return this.ipArr.reduce( (ip , val) => {
        return ip + '.' + this[val]
      },"")
    },
    // 触发父组件方法
    handleSave(val) {
      this.$emit(val);
    }
  }
};
</script>
<style lang="scss">
.ip-address {
  display: flex;
  margin-left: 10px;
  width: 294px;
  height: 36px;
  .ip-address__input {
    .el-input__inner {
      height: 34px;
    }
    .el-input__inner:focus {
      border: 1px solid #DCDFE6;
    }
  }
  .ip-address__input:nth-child(1) {
    .el-input__inner {
      border-right: 0px !important;
      border-radius: 4px 0 0 4px;
    }
  }
  .ip-address__input:nth-child(3),
  .ip-address__input:nth-child(5) {
    .el-input__inner {
      border-right: 0px !important;
      border-left: 0px !important;
      border-radius: 0;
    }
  }
  .ip-address__input:nth-child(7) {
    .el-input__inner {
      border-radius: 0 4px 4px 0;
      border-left: 0px !important;
    }
  }
}
</style>

5、实现效果

在这里插入图片描述

  • 作者:微不足道的张三
  • 原文链接:https://blog.csdn.net/qq_44708990/article/details/119416220
    更新时间:2023-01-09 20:25:55