由于element-ui 和 iview-ui 组件库,目前暂未提供 IP 类的组件,小编组件封装了一个vue的IP组件,仅供大家使用和学习探讨;
之前也有写有 IP组件的文章,这次是二次优化,
1.优化了之前没输入3位数后自动跑到 下一个空格里面,本次优化后,每输入3位数值后,需要输入 " ." 或者enter键,才会 跳到 下一个空格里面;
2. 优化了,每次调用后,再次点击新增数据的时候, 清空上次的数据
代码如下:
父组件:
<FormItem label="设备IP:" prop="ip">
<ip-check v-model="formAddDevice.ip"> </ip-check>
</FormItem>
import ipCheck from '@/components/ipModal/ipCheck.vue';
components: {'ipCheck': ipCheck},
data(){
// 设备IP 验证
const validateip = (rule, value, callback) => {
if (value === '') {
return callback(new Error('请输入设备IP!'))
} else {
return callback()
}
}
return:{
formAddDevice: {
ip: '',
},
addRules:{
ip: [
{ required: true, type: 'string', message: 'IP不能为空!', trigger: 'blur' },
{ validator: validateip, trigger: 'blur' }
]
}
}
}
子组件代码:
<template>
<div class="ipAdress">
<ul id="id1" class="ipInput" :class="{ isDisabled: isDisabled }">
<li v-for="(item, index) in ipAdress" :key="index">
<input
ref="ipInput"
v-model="item.value"
:tabindex="'ipInput' + (index + 1)"
:class="'ipAdress' + (index + 1)"
autocomplete="off"
:readonly="isDisabled"
:maxlength="3"
type="tel"
pattern="[0-9]{1,3}"
:disabled="isDisabled || detailsFlag"
@blur="blurFocus(index)"
@input="checkIpVal(item, index, $event)"
@keyup="turnIpPOS(item, index, $event)"
@keydown="delteIP(item, index, $event)"
>
<span v-if="index < 3">.</span>
</li>
</ul>
<!-- <div class="error">请输入IP地址!</div> -->
</div>
</template>
<script>
export default {
model: {
prop: 'ipStr',
event: 'change'
},
props: {
ipStr: {
type: String,
default: ''
},
ipType: {
type: String,
default: ''
},
isDisabled: {
type: Boolean,
default: false
},
width: {
type: String,
default: '100%'
}
},
data() {
return {
title_name: '',
detailsFlag: false, // 详情页是否:disabled
erro_ip: true,
ipAdress: [
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
}
],
isWX: navigator.userAgent.toLowerCase().match(/MicroMessenger/i) === 'micromessenger'
}
},
watch: {
ipStr: {
immediate: true,
handler: function(vall) {
const val = vall
let nArr = []
if (val && val.includes('.') && val.length > 0) {
const valArr = val.split('.')
const m = valArr.length
for (let i = 0; i < 4; i++) {
if (valArr[i] === 'null' || valArr[i] === 'undefined') {
valArr[i] = ''
}
if (i < m) {
nArr.push({
value: valArr[i]
})
} else {
nArr.push({
value: ''
})
}
}
} else {
nArr = [{ value: '' }, { value: '' }, { value: '' }, { value: '' }]
}
this.ipAdress = nArr
}
},
title_name: function(data) {
// console.log("title_name:",data)
if (data.indexOf('详情') !== -1) {
// 详情
this.detailsFlag = true
} else {
// 新增或者编辑
this.detailsFlag = false
}
}
},
destroyed() {
this.$destroy()
},
methods: {
// methods
blurFocus(index) {
if (index === 3) {
this.$emit('blur')
}
},
checkIpVal(item, index, event) {
const self = this
// wx
if (this.isWX) {
const e = event || window.event
const keyCode = e.data
// .向右跳转
if (keyCode === '.') {
e.preventDefault()
e.returnValue = false
item.value = item.value.replace(/[^\d]/g, '').replace(/[\.]/g, '')
if (index < 3) {
self.$refs.ipInput[index + 1].focus()
}
return false
}
}
// const isNo = /^[0-9]{1,3}$/g
if (/[^\d]/g.test(item.value)) {
const cache = JSON.parse(JSON.stringify(self.ipAdress))
cache[index].value = item.value.replace(/[^\d]/g, '').replace(/[\.]/g, '')
self.ipAdress = cache
return false
}
if (item.value.replace(/[^\d]/g, '').length >= 3) {
let val = parseInt(item.value.replace(/[^\d]/g, ''), 10)
if (isNaN(val)) {
val = ''
} else if (val > 255) {
val = 255
} else {
val = val < 0 ? 0 : val
}
item.value = String(val)
this.$set(this.ipAdress, index, item)
}
let ns = ''
this.ipAdress.forEach((item) => (ns += '.' + item.value))
// 给父组件传值 ip的值
if (true) {
let ip = ''
this.ipAdress.map((v) => {
ip = ip + '.' + v.value
})
this.$emit('change', ip.substring(1))
}
},
turnIpPOS(item, index, event) {
const self = this
const e = event || window.event
if (e.keyCode === 37) {
if (index !== 0) {
self.$refs.ipInput[index - 1].focus()
}
}
// 右箭头、回车键、空格键、冒号均向右跳转,右一不做任何措施
if (e.keyCode === 39 || e.keyCode === 13 || e.keyCode === 32 || e.keyCode === 110 || e.keyCode === 46 || e.keyCode === 190) {
e.preventDefault()
e.returnValue = false
if (index < 3) {
self.$refs.ipInput[index + 1].focus()
}
return false
}
},
delteIP(item, index, event) {
// console.log('deleteIP:',item, index, event)
const self = this
const e = event || window.event
let val = parseInt(item.value.replace(/[^\d]/g, ''), 10)
val = isNaN(val) ? '' : val
if (e.keyCode === 8 && index > 0 && val.length === 0) {
self.$refs.ipInput[index - 1].focus()
}
}
}
}
</script>
<style lang="scss">
.ipAdress {
position: relative;
.error {
position: absolute;
padding-top: 10px;
display: inline-block;
margin: 0%;
padding: 0%;
color: #f56c6c;
line-height: 1;
font-size: 12px;
}
}
.ipInput {
width: 100%;
height: 29px;
box-sizing: border-box;
line-height: inherit;
border: 1px solid #dcdfe6;
background-color: #fff;
overflow: hidden;
border-radius: 4px;
padding: 0;
margin: 0;
display: inline-block;
vertical-align: middle;
outline: transparent;
font-size: 0;
text-indent: 0;
background: #fff;
display: flex;
flex-direction: row;
}
.ipInput.isDisabled {
background: transparent;
}
.ipInput.isDisabled li {
cursor: not-allowed;
height: 29px;
}
.ipInput.isDisabled li input {
cursor: not-allowed;
}
.ipInput li {
display: inline-block;
width: 25%;
height: 29px;
box-sizing: border-box;
font-size: 0;
display: flex;
flex-direction: row;
}
.ipInput .ivu-input:focus {
box-shadow: none;
}
.ipInput li input {
appearance: none;
padding: 10px 5px;
width: calc(100% - 3px);
text-align: center;
outline: none;
border: none;
color: #000;
box-sizing: border-box;
font-size: 12px;
height: 29px;
}
.ipInput li input.disabled {
background: transparent;
}
.ipInput input:disabled {
background-color: #f3f3f3;
opacity: 1;
cursor: not-allowed;
color: #ccc;
}
.ipInput li span {
display: inline-block;
font-size: 20px;
width: 4px;
height: 4px;
color: #000;
}
</style>
补充说明:关于子组件参数的表单验证: