项目中查询条件要输入ip地址所以就索性自己封装一个ip地址输入框的组件 使用的是vue3+element 也可自行换成别的UI组件库
以下附上代码,直接复制就可以使用
引用
import ipInput from '@/components/ip-address-input.vue'
<ip-input v-model:value=""></ip-input>
html部分
<template>
<div class="ipInput">
<template v-for="index in 4" :key="index">
<el-input
v-model.number="ipAddress[`ip` + index]"
maxlength="3"
:ref="el => setItemRef(el, index)"
@paste="handlePaste(index, $event)"
@keyup="keyupEvent(index, $event)"
@blur="submitIp"
@input="val => handleInpIp(val, index)"
></el-input>
<span class="dot" v-if="index !== 4">.</span>
</template>
</div>
</template>
js部分
import { ref, nextTick, reactive, onMounted } from 'vue'
import Message from '@/utils/message.js'
let props = defineProps(['value'])
const emits = defineEmits(['update:value'])
const ipAddress = reactive({
ip1: '',
ip2: '',
ip3: '',
ip4: ''
})
let ipRefs = ref({})
const setItemRef = (el, key) => {
ipRefs.value[key] = el
}
function handlePaste(index, event) {
const e = event || window.event
let ipValue = e.clipboardData.getData('Text')
if (ipValue != null && ipValue != undefined && ipValue !== '') {
let reg =
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
if (!reg.test(ipValue)) {
Message.error('请输入正确的IP地址!')
setTimeout(() => {
ipAddress.ip1 = null
ipAddress.ip2 = null
ipAddress.ip3 = null
ipAddress.ip4 = null
}, 600)
ipRefs.value[index - 1].value.focus()
} else {
let ipList = ipValue.split('.')
setTimeout(() => {
ipAddress.ip1 = ipList[0]
ipAddress.ip2 = ipList[1]
ipAddress.ip3 = ipList[2]
ipAddress.ip4 = ipList[3]
ipRefs.value[4].focus()
}, 5)
}
}
}
function keyupEvent(index, e) {
if (e.keyCode === 110 || e.keyCode === 190) {
index < 4 && ipRefs.value[index + 1].focus()
ipAddress['ip' + index + 1] = ''
}
if (e.keyCode == 8) {
let ipVal = ipAddress['ip' + index]
if (ipVal === '' || (ipVal == null && index !== 1)) {
ipRefs.value[index - 1].focus()
}
}
if (e.keyCode == 37) {
if (e.srcElement.selectionStart === 0) {
ipRefs.value[index - 1].focus()
}
}
if (e.keyCode == 39) {
if (e.srcElement.selectionStart === e.srcElement.value.length) {
ipRefs.value[index + 1].focus()
}
}
}
function handleInpIp(val, key) {
if (parseInt(val) > 255) {
ipAddress[`ip` + key] = 255
key < 4 && ipRefs.value[key + 1].focus()
}
else if (parseInt(val) <= 255 && parseInt(val) >= 100) {
key < 4 && ipRefs.value[key + 1].focus()
}
}
function submitIp() {
const invalidIpPart = Object.values(ipAddress).some(part => part == null || part === '')
if (invalidIpPart) {
emits('update:value', '')
} else {
const ipVal = Object.values(ipAddress).join('.')
if (!ipVal.match(/^(\d{1,3}\.){3}\d{1,3}$/)) {
Message.error('请输入正确的 IP 地址!')
Object.keys(ipAddress).forEach(key => (ipAddress[key] = null))
nextTick(() => ipRefs.value[0].focus())
} else {
emits('update:value', ipVal)
}
}
}
onMounted(() => {
if (props.value) {
const ipList = props.value.split('.')
Object.keys(ipAddress).forEach((key, index) => (ipAddress[key] = ipList[index]))
}
})
css部分(样式可按照项目的需求进行修改)
.ipInput {
width: 200px;
height: 34px;
display: flex;
align-items: center;
border: 1px solid #dcdfe6;
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
.item {
display: flex;
align-items: center;
.point {
user-select: none;
}
}
:deep(.el-input .el-input__wrapper) {
border: none !important;
box-shadow: none !important;
padding: 0px 10px !important;
}
:deep(.el-input__inner) {
width: 100%;
padding: 0 !important;
}
}