1、问题
页面开发的时候,有一个需求是弹窗中使用与 IP 地址相同功能的输入框(弹窗宽度固定),本来想使用 element 的输入框的插槽实现,最后发现行不通,只能手写一个这样的组件了
原型要求:
2、要求:
- 每个 IP 地址框数据长度不能超过三位
- 展示上需要用原点分割每一个 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>