父组件:
<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;
下面是我在学习HTML和CSS的时候整理的一些笔记,有兴趣的可以看下:

### 进阶阶段
进阶阶段,开始攻 JS,对于刚接触 JS 的初学者,确实比学习 HTML 和 CSS 有难度,但是只要肯下功夫,这部分对于你来说,也不是什么大问题。
JS 内容涉及到的知识点较多,看到网上有很多人建议你从头到尾抱着那本《JavaScript高级程序设计》学,我是不建议的,毕竟刚接触 JS 谁能看得下去,当时我也不能,也没那样做。
我这部分的学习技巧是,增加次数,减少单次看的内容。就是说,第一遍学习 JS 走马观花的看,看个大概,去找视频以及网站学习,不建议直接看书。因为看书看不下去的时候很打击你学下去的信心。
然后通过一些网站的小例子,开始动手敲代码,一定要去实践、实践、实践,这一遍是为了更好的去熟悉 JS 的语法。别只顾着来回的看知识点,眼高手低可不是个好习惯,我在这吃过亏,你懂的。
**1、JavaScript 和 ES6**
在这个过程你会发现,有很多 JS 知识点你并不能更好的理解为什么这么设计,以及这样设计的好处是什么,这就逼着让你去学习这单个知识点的来龙去脉,去哪学?第一,书籍,我知道你不喜欢看,我最近通过刷大厂面试题整理了一份前端核心知识笔记,比较书籍更精简,一句废话都没有,这份笔记也让我通过跳槽从8k涨成20k。

**2、前端框架**
前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。
以 Vue 为例,我整理了如下的面试题。

**开源分享:https://docs.qq.com/doc/DSmRnRGxvUkxTREhO**