由于在使用ui框架中没有合适的ip地址类型输入框,所以自己封装了一个
功能:
- 可增、删、改
- 可在每个input间进行切换
- 回车跳转
<template>
<ul>
<li v-for="(item,index) in ipAddress" :key="index">
<input ref="ipInput" v-model="item.value" type="text"
@input="checkIpVal(item)"
@keyup="turnIpPosition(item,index,$event)" />
<div></div>
</li>
</ul>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
}
},
data() {
return {
ipAddress: [
{
value: ''
},{
value: ''
},{
value: ''
},{
value: ''
}
]
}
},
watch: {
ipAddress: { // 双向数据绑定的value
handler: function (newVal, oldVal) {
console.log(newVal, oldVal);
let str = ''
for (const i in this.ipAddress) {
str += this.formatter(this.ipAddress[i].value)
}
if (str === '000000000000') {
str = ''
}
this.$emit('input', str);
},
deep: true
}
},
methods: {
// 格式化补零方法
formatter(val) {
let value = val.toString()
if (value.length === 2) {
value = '0' + value
} else if (value.length === 1) {
value = '00' + value
} else if (value.length === 0) {
value = '000'
}
return value
},
// 检查ip输入为0-255
checkIpVal(item) {
//确保每个值都处于0-255
let val = item.value;
// 处理非数字
val = val.toString().replace(/[^0-9]/g,'');
val = parseInt(val, 10);
if(isNaN(val)) {
val = '';
} else {
val = val < 0 ? 0 : val;
val = val > 255 ? 255 : val;
}
item.value = val;
},
// 光标位置判断
turnIpPosition(item, index, event) {
let self = this;
let e = event || window.event;
if (e.keyCode === 37) { // 左箭头向左跳转,左一不做任何措施
// 事件监听器对象的起点位置
if(index !== 0 && e.currentTarget.selectionStart === 0) {
self.$refs.ipInput[index - 1].focus();
}
} else if (e.keyCode == 39) { // 右箭头向右跳转,右一不做任何措施
if(index !== 3 && e.currentTarget.selectionStart === item.value.toString().length) {
self.$refs.ipInput[index + 1].focus();
}
} else if (e.keyCode === 8) { // 删除键把当前数据删除完毕后会跳转到前一个input,左一不做任何处理
if(index !== 0 && item.value === '') {
self.$refs.ipInput[index - 1].focus();
}
} else if (e.keyCode === 13 || e.keyCode === 32 || e.keyCode === 190) {// 回车键、空格键、冒号均向右跳转,右一不做任何措施
if(index !== 3) {
self.$refs.ipInput[index + 1].focus();
}
} else if (item.value.toString().length === 3) { // 满3位,光标自动向下一个文本框
if(index !== 3) {
self.$refs.ipInput[index + 1].focus();
}
}
},
setIPInit(ipVal){
const ipVals = ipVal.split(".");
for (const i in this.ipAddress) {
this.ipAddress[i].value = ipVals[i] ?? "";
}
},
}
}
</script>
调用组件
由于v-model的本质是 v-bind:value="value" @input="val=> value = val",但它会默认以prop中的value和input事件绑定,所以子组件传递的 str ipaddress 进行了绑定
<ip-address-input
ref="ip"
v-model="ipaddress"
:value="ipaddress"
>
</ip-address-input>