前端 ip地址框
用到了键盘监听事件 document.onkeydown 全局键盘监听
input 焦点出发 document.querySelector(‘#ip1’).focus()
下面是vue3语法,ant-design-vue 框架 react语法类似,主要里里面的方法复制走就好了
主要代码(vue2和vue3两种写法)
vue3语法
<template>
<a-row>
<a-col :span="14">
<div class="ip-input">
<input
id="ip1"
v-model="ipAddress.ip1"
ref="input1"
@input="handleInput(1)"
@keydown="handleKeyDown($event, 1)"
maxlength="3"
/>
<span>.</span>
<input
id="ip2"
v-model="ipAddress.ip2"
ref="input2"
@input="handleInput(2)"
@keydown="handleKeyDown($event, 2)"
maxlength="3"
/>
<span>.</span>
<input
id="ip3"
v-model="ipAddress.ip3"
ref="input3"
@input="handleInput(3)"
@keydown="handleKeyDown($event, 3)"
maxlength="3"
/>
<span>.</span>
<input
id="ip4"
v-model="ipAddress.ip4"
ref="input4"
@input="handleInput(4)"
@keydown="handleKeyDown($event, 4)"
@keyup.enter.native="saveOk"
maxlength="3"
/>
</div>
</a-col>
<a-col :span="10">
<div style="line-height: 40px">
<a-button @click="saveOk" type="primary">{{ $t('modal.ok') }}</a-button
>
<a-button @click="resetIp">{{ $t('fileSelect.reset') }}</a-button>
</div>
</a-col>
</a-row>
<br />
<div style="color: #666"><sapn style="color: #f00">* </sapn>{{ $t('login.hostIpNote') }}</div>
</template>
<script lang="ts" setup>
import { message } from 'ant-design-vue';
import i18n from '/@/language';
import { onMounted, ref, reactive } from 'vue';
const IP_RULES =
/^(\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])$/;
const props = defineProps({
value: {
type: String,
},
});
const emit = defineEmits(['saveOk']);
const ipAddress: any = reactive({
ip1: '',
ip2: '',
ip3: '',
ip4: '',
});
onMounted(() => {
const Store = require('electron-store');
const store = new Store();
let ipArr = store.get('serverAddressIp')?.split('.');
if (ipArr) {
ipAddress.ip1 = ipArr[0];
ipAddress.ip2 = ipArr[1];
ipAddress.ip3 = ipArr[2];
ipAddress.ip4 = ipArr[3];
}
});
const handleInput = (index: number) => {
ipAddress[`ip${index}`] = ipAddress[`ip${index}`].replace(/[^0-9]/g, '');
let ip = ipAddress[`ip${index}`];
if (ip.length > 1 && ip[0] === '0') {
ipAddress[`ip${index}`] = ip.slice(1);
}
if (ip > 255) {
ipAddress[`ip${index}`] = '255';
}
if (ip.length === 3 || ip[0] === '0') {
let nextIndex = index + 1;
if (nextIndex <= 4) {
document.querySelector(`#ip${nextIndex}`).focus();
}
}
};
const handleKeyDown = (event: any, index: number) => {
let ip = ipAddress[`ip${index}`];
if (event.keyCode == 8 && 0 == document.getElementById(`ip${index}`).selectionStart) {
let nextIndex = index - 1;
if (nextIndex >= 1) {
console.log(nextIndex);
document.querySelector(`#ip${nextIndex}`).focus();
document
.getElementById(`ip${nextIndex}`)
.setSelectionRange(ipAddress[`ip${nextIndex}`].length, ipAddress[`ip${nextIndex}`].length);
}
} else if (
event.keyCode == 46 &&
ip.length == document.getElementById(`ip${index}`).selectionStart
) {
let nextIndex = index + 1;
if (nextIndex <= 4) {
document.querySelector(`#ip${nextIndex}`).focus();
document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
}
} else if (event.keyCode == 37 && 0 == document.getElementById(`ip${index}`).selectionStart) {
let nextIndex = index - 1;
if (nextIndex >= 1) {
document.querySelector(`#ip${nextIndex}`).focus();
document
.getElementById(`ip${nextIndex}`)
.setSelectionRange(ipAddress[`ip${nextIndex}`].length, ipAddress[`ip${nextIndex}`].length);
}
} else if (
event.keyCode == 39 &&
ip.length == document.getElementById(`ip${index}`).selectionStart
) {
let nextIndex = index + 1;
if (nextIndex <= 4) {
document.querySelector(`#ip${nextIndex}`).focus();
document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
}
} else if (event.keyCode == 110 || event.keyCode == 190) {
let nextIndex = index + 1;
if (nextIndex <= 4) {
document.querySelector(`#ip${nextIndex}`).focus();
}
} else {
return false;
}
};
const saveOk = () => {
if (ipAddress.ip1 == '' || ipAddress.ip2 == '' || ipAddress.ip3 == '' || ipAddress.ip4 == '') {
message.warning(i18n.global.t('login.ipRules'));
} else {
console.log('ip');
const ip = ipAddress.ip1 + '.' + ipAddress.ip2 + '.' + ipAddress.ip3 + '.' + ipAddress.ip4;
emit('saveOk', ip, IP_RULES.test(ip));
}
};
const resetIp = () => {
ipAddress.ip1 = '';
ipAddress.ip2 = '';
ipAddress.ip3 = '';
ipAddress.ip4 = '';
};
</script>
<style scoped>
.ip-input {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 40px;
/* border: 1px solid #ccc; */
border: 1px solid #204fc7;
border-radius: 4px;
padding: 0 10px;
box-sizing: border-box;
font-size: 16px;
}
.ip-input input {
width: 40px;
height: 90%;
border: none;
outline: none;
text-align: center;
font-size: 16px;
}
.ip-input span {
font-size: 16px;
}
</style>
vue2语法
<template>
<a-row>
<a-col :span="14">
<div class="ip-input">
<input
id="ip1"
v-model="ip1"
ref="input1"
@input="handleInput(1)"
@keydown="handleKeyDown($event, 1)"
maxlength="3"
/>
<span>.</span>
<input
id="ip2"
v-model="ip2"
ref="input2"
@input="handleInput(2)"
@keydown="handleKeyDown($event, 2)"
maxlength="3"
/>
<span>.</span>
<input
id="ip3"
v-model="ip3"
ref="input3"
@input="handleInput(3)"
@keydown="handleKeyDown($event, 3)"
maxlength="3"
/>
<span>.</span>
<input
id="ip4"
v-model="ip4"
ref="input4"
@input="handleInput(4)"
@keydown="handleKeyDown($event, 4)"
@keyup.enter.native="saveOk"
maxlength="3"
/>
</div>
</a-col>
<a-col :span="10">
<div style="line-height: 40px;">
<a-button @click="saveOk" type="primary">{{ $t('modal.ok') }}</a-button
>
<a-button @click="resetIp">{{ $t('fileSelect.reset') }}</a-button>
</div>
</a-col>
</a-row>
<br />
<div style="color: #666"><sapn style="color: #f00">* </sapn>{{ $t('login.hostIpNote') }}</div>
</template>
<script>
import { message } from 'ant-design-vue';
import i18n from '/@/language';
const IP_RULES =
/^(\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])$/;
export default {
name: 'IpModel',
props: {
IP: String,
},
data() {
return {
ip1: '',
ip2: '',
ip3: '',
ip4: '',
};
},
created() {
const Store = require('electron-store');
const store = new Store();
let ipArr = store.get('serverAddressIp')?.split('.');
if (ipArr) {
this.ip1 = ipArr[0];
this.ip2 = ipArr[1];
this.ip3 = ipArr[2];
this.ip4 = ipArr[3];
}
},
methods: {
handleInput(index) {
this[`ip${index}`] = this[`ip${index}`].replace(/[^0-9]/g, '');
let ip = this[`ip${index}`];
if (ip.length > 1 && ip[0] === '0') {
this[`ip${index}`] = ip.slice(1);
}
if (ip > 255) {
this[`ip${index}`] = '255';
}
if (ip.length === 3 || ip[0] === '0') {
let nextIndex = index + 1;
if (nextIndex <= 4) {
this.$refs[`input${nextIndex}`].focus();
}
}
},
handleKeyDown(event, index) {
let ip = this[`ip${index}`];
if (event.keyCode == 8 && 0 == document.getElementById(`ip${index}`).selectionStart) {
let nextIndex = index - 1;
if (nextIndex >= 1) {
this.$refs[`input${nextIndex}`].focus();
document
.getElementById(`ip${nextIndex}`)
.setSelectionRange(this[`ip${nextIndex}`].length, this[`ip${nextIndex}`].length);
}
} else if (
event.keyCode == 46 &&
ip.length == document.getElementById(`ip${index}`).selectionStart
) {
let nextIndex = index + 1;
if (nextIndex <= 4) {
this.$refs[`input${nextIndex}`].focus();
document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
}
} else if (event.keyCode == 37 && 0 == document.getElementById(`ip${index}`).selectionStart) {
let nextIndex = index - 1;
if (nextIndex >= 1) {
this.$refs[`input${nextIndex}`].focus();
document
.getElementById(`ip${nextIndex}`)
.setSelectionRange(this[`ip${nextIndex}`].length, this[`ip${nextIndex}`].length);
}
} else if (
event.keyCode == 39 &&
ip.length == document.getElementById(`ip${index}`).selectionStart
) {
let nextIndex = index + 1;
if (nextIndex <= 4) {
this.$refs[`input${nextIndex}`].focus();
document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
}
} else if (event.keyCode == 110 || event.keyCode == 190) {
let nextIndex = index + 1;
if (nextIndex <= 4) {
this.$refs[`input${nextIndex}`].focus();
}
} else {
return false;
}
},
saveOk() {
if (this.ip1 == '' || this.ip2 == '' || this.ip3 == '' || this.ip4 == '') {
message.warning(i18n.global.t('login.ipRules'));
} else {
console.log('ip');
const ip = this.ip1 + '.' + this.ip2 + '.' + this.ip3 + '.' + this.ip4;
this.$emit('saveOk', ip, IP_RULES.test(ip));
// this.$emit('changeIP', ip);
}
},
IpModelCancel() {
this.ip1 = this.IP.split('.')[0];
this.ip2 = this.IP.split('.')[1];
this.ip3 = this.IP.split('.')[2];
this.ip4 = this.IP.split('.')[3];
},
resetIp() {
this.ip1 = '';
this.ip2 = '';
this.ip3 = '';
this.ip4 = '';
},
},
};
</script>
<style scoped>
.ip-input {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 40px;
border: 1px solid #ccc;
border-radius: 4px;
padding: 0 10px;
box-sizing: border-box;
font-size: 16px;
}
.ip-input input {
width: 40px;
height: 90%;
border: none;
outline: none;
text-align: center;
font-size: 16px;
}
.ip-input span {
font-size: 16px;
}
</style>
引用
<template>
<a-modal
:visible="identifying.IpVisible"
:title="$t('login.hostIp')"
width="445px"
@cancel="() => (identifying.IpVisible = false)"
zIndex="1"
:footer="null"
>
<a-form-item label="">
<ipInputVue3 @cancel="() => (identifying.IpVisible = false)" @saveOk="saveIp" />
</a-form-item>
</a-modal>
</template>
<script lang="ts" setup>
import { onMounted, reactive, watch } from 'vue';
import { message } from 'ant-design-vue';
import ipInputVue3 from '/@/components/ip/index.vue';
const props = defineProps({
value: {
type: String,
default: '',
},
});
const identifying = reactive({
IpVisible: false,
});
onMounted(() => {});
const saveIp = (ipAddress: string, isRight: Boolean) => {
console.log(ipAddress);
if (isRight) {
message.warning('ip格式正确,继续操作');
} else {
message.warning('ip格式不正确');
}
};
</script>
<style lang="less" scoped></style>