【前端小点】Vue3中的IP输入框组件

2024-06-04 6277阅读

本文章记录,如何在vue3项目开发中,使用ip输入框组件.

之前写过vue2版本的ip组件,为了更好的适应vue3,此次进行vue3代码重写

几乎涵盖电脑上自带的IP输入框效果,如有问题,欢迎留言探讨.

先上效果图:

【前端小点】Vue3中的IP输入框组件 第1张

禁用效果图:

【前端小点】Vue3中的IP输入框组件 第2张

主要是组件的开发,代码如下,可直接拷贝使用.

大概思路就是: 使用四个输入框拼接,然后给输入内容添加校验操作,添加光标移动,

使用v-model语法糖特性

组件: IpAddress.vue
  
import { ref, watch } from 'vue' // 接收来自上层的数据 const props = defineProps(['value', 'disabled']) // 更新数据 const $emits = defineEmits(['update:value', 'blur']) // 存储四个ref const ipInputRefs = ref([]); // 存储左右标识位 let markFlag = ref([ { left: false, right: false }, { left: false, right: false }, { left: false, right: false }, { left: false, right: false } ]) // 更新标识 let flag = ref(false) // 鼠标点击 const handleMouseUp = (index: any) => { let input = ipInputRefs.value[index] // 全为false markFlag.value.forEach(item => { item.left = false item.right = false }) // 证明在开始阶段 if (input.selectionStart == 0) { console.log('鼠标设置了,', index) markFlag.value[index].left = true } else { markFlag.value[index].left = false } // 证明在结束 if (input.selectionStart == (input.value || '').length) { markFlag.value[index].right = true } else { markFlag.value[index].right = false } } // 获取四个input refs const getInputRef = (el: any, index: number) => { if (el) { ipInputRefs.value[index] = el; } }; // 声明IP存储类型 interface IpType { value: string } // 定义要显示的四个ip let ipAddress = ref([ { value: "", }, { value: "", }, { value: "", }, { value: "", }, ]) // 初始化显示数据 const initShowData = () => { // 判断不合理行为 if (props.value === '') { ipAddress.value.forEach(item => { item.value = '' }) } else { let ipList = props.value.split('.') ipAddress.value.forEach((item: IpType, index: number) => { item.value = ipList[index] }) } } // 检查ip输入 const checkIpVal = (item: any) => { let val = item.value; console.log(val, '===========') // 处理非数字 val = val.toString().replace(/[^0-9]/g, ""); val = parseInt(val, 10); if (isNaN(val)) { val = ""; } else { val = val 255) { // 判断val是几位数 let num = (val + '').length if (num > 3) { val = parseInt((val + '').substring(0, 3)) } else { val = 255 } } } item.value = val; console.log(item.value, '=========') } // 判断光标左右移动位置 const turnIpPosition = (item: IpType, index: number, event: any) => { let e = event || window.event; if (e.keyCode === 37) { // 左箭头向左跳转,左一不做任何措施 if (index == 0) { return } if (e.currentTarget.selectionStart === 0) { if (markFlag.value[index].left) { handleFocus(index - 1, 'toLeft') markFlag.value[index].left = false markFlag.value[index].right = false } else { console.log('左键设置了,', index) markFlag.value[index].left = true } } else { markFlag.value[index].right = false markFlag.value[index].left = false } } else if (e.keyCode == 39) { // 右箭头向右跳转,右一不做任何措施 markFlag.value[index].left = false let start = e.currentTarget.selectionStart if (index != 3 && start === item.value.toString().length) { if (markFlag.value[index].right) { handleFocus(index + 1, 'toRight') markFlag.value[index].left = false markFlag.value[index].right = false } else { markFlag.value[index].right = true } } else { markFlag.value[index].right = false } } else if (e.keyCode === 8) { console.log('删除键把当前数据删除完毕后会跳转到前一个input') // 删除键把当前数据删除完毕后会跳转到前一个input,左一不做任何处理 if (index !== 0 && e.currentTarget.selectionStart === 0) { if (markFlag.value[index].left) { ipInputRefs.value[index - 1].focus(); markFlag.value[index].left = false } else { console.log('左键设置了删除,', index) markFlag.value[index].left = true } } } else if (e.keyCode === 13 || e.keyCode === 32) { console.log('回车键、空格键、冒号均向右跳转,右一不做任何措施') // 回车键、空格键、冒号均向右跳转,右一不做任何措施 if (index !== 3) { ipInputRefs.value[index + 1].focus(); } } else if (e.keyCode === 110 || e.keyCode === 190) { // 点 . 向右跳转,右一不做任何措施 console.log('点击') if (item.value == '') { return } if (index !== 3) { ipInputRefs.value[index + 1].select(); } } else if (item.value.toString().length === 3) { console.log('满3位,光标自动向下一个文本框') // 满3位,光标自动向下一个文本框. if (index !== 3) { ipInputRefs.value[index + 1].setSelectionRange(0, 0) } } } // 处理聚焦 const handleFocus = (index: number, direction: string) => { // 设置当前位置为选中状态 toRight:从左边来的 let input = ipInputRefs.value[index] input.focus() let value = input.value // null 左右全部设置为true,可以直接跳转 if ((value || '').length == 0) { markFlag.value[index].right = true markFlag.value[index].left = true } else { if (direction == 'toRight') { // 可以直接跳回 console.log('右键focus,', index) markFlag.value[index].left = true // 设置光标为左边第一个 ipInputRefs.value[index].setSelectionRange(0, 0) // 设置上一个的右边标识为false markFlag.value[index - 1] && (markFlag.value[index - 1].right = false) } else { // 直接跳回 markFlag.value[index].right = true // 设置后一个侧边为false markFlag.value[index + 1] && (markFlag.value[index + 1].left = false) } } } // 格式化补零方法 const formatter = (val: string) => { 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; } // 监听数据变化,并初始化显示四个数据 watch(() => props.value, () => { console.log('变化了~', props.value); if(flag.value){ }else{ initShowData() } }, { immediate: true }) // 监听ipAddress数据变化 watch(ipAddress, () => { let str = ""; for (const i in ipAddress.value) { str += formatter(ipAddress.value[i].value); } if (str === "000000000000") { str = ""; } else { str = ipAddress.value.map(item => { if (item.value !== null) { return item.value + '' } else { return '0' } }).join(".") } $emits('update:value', str) flag.value = true setTimeout(() => { flag.value = false }, 100) }, { deep: true }) const handleBlur = () => { $emits('blur') } .disabled { cursor: not-allowed; background-color: #f5f7fa; .ipAdress { li { .ipInputClass { color: #c3c4cc; cursor: not-allowed; } } } } .ipAdress { display: flex; border: 1px solid #dcdfe6; border-radius: 4px; line-height: 40px; width: 100%; height: 40px; padding-inline-start: 0px; padding-left: 10px; padding-right: 10px; box-sizing: border-box; margin: 0; } .ipAdress li { position: relative; margin: 0; list-style-type: none; } .ipInputClass { border: none; width: 50px; height: 23px; text-align: center; color: #606266; background: transparent; } .ipAdress li div { position: absolute; bottom: 12px; right: 0; border-radius: 50%; background: #b6b8bc; width: 2px; height: 2px; } /*只需要3个div*/ .ipAdress li:last-child div { display: none; } /*取消掉默认的input focus状态*/ .ipAdress input:focus { outline: none; }

注册为组件以后,在页面中使用如下,当然,组件名自己定义,我这里组件名是IpAddress

// ipAddress双向绑定,handleBlur 可以在失去光标时,做校验等操作


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]