1.实列图片
2.代码部分
<template><div class="ami-input-ip"><ul class="ipAdress" :class="[actived]" @mouseover="changeColor()"><li v-for="(item,index) in ipAddress" :key="index"><ami-input class="ipInputClass"ref="ipInput"type="text":size="size"v-model="item.value"v-bind="$attrs":disabled="disabled":readonly="readonly"@input="checkIpVal(item)"@keyup="turnIpPosition(item,index,$event)"/><div class="ip-box"></div></li></ul><div class="icon" v-if="this.clearable&&this.readonly!==true"><i class="ami-icon-circle-close" @click="clear()"></i></div></div></template><script>export default {name: 'AmiInputIp',props: {size: {type: String,default: 'large'},// 侦听的值value: {type: String,default: ''},// 设置返回值类型formatStyle: {type: String,default: 'node'},// 禁用disabled: {type: Boolean,default: false},// 是否只读readonly: {type: Boolean,default: false}},data() {return {actived: '',clearable: false,ipAddress: [{value: ''}, {value: ''}, {value: ''}, {value: ''}]};},mounted() {if (this.value && this.value.length > 0 && this.value.split('.').length === 4) {var arr = this.value.split('.');for (var i in arr) {this.ipAddress[i].value = arr[i];}}},watch: {// 双向数据绑定的valueipAddress: {handler(newVal, oldVal) {let str = '';for (const i in this.ipAddress) {if (this.formatStyle === 'noNode') {str += this.formatter(this.ipAddress[i].value);} else {if (str.length > 0) {str += '.';}str += this.ipAddress[i].value === '' ? '000' : this.ipAddress[i].value;}}if (str === '000000000000' || str === '000.000.000.000') {str = '';}// 判断输入框是有值this.clearable = str.length > 0;this.$emit('input', str);},deep: true}},methods: {// 清空clear() {for (var i in this.ipAddress) {this.ipAddress[i].value = '';}},// 格式化补零formatter(val) {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;},// 检查ip输入是否为0-255checkIpVal(item) {// 确保每个值都处于0-255var val = item.value;// 处理非数字val = val.toString().replace(/[^0-9]/g, '');val = parseInt(val, 10);if (isNaN(val)) {val = '';} else {val = val < 0 ? 0 : val;val = val > 255 ? 255 : val;}item.value = val;},// 光标位置判断turnIpPosition(item, index, event) {let self = this;let e = event || window.event;if (e.keyCode === 37) {// 左箭头向左跳转,左一不做任何措施if (index !== 0 && e.currentTarget.selectionStart === 0) {self.$refs.ipInput[index - 1].focus();}} else if (e.keyCode === 39) {// 右箭头向右跳转,右一不做任何措施if (index !== 3 && e.currentTarget.selectionStart === item.value.toString().length) {self.$refs.ipInput[index + 1].focus();}} else if (e.keyCode === 8) {// 删除键把当前数据删除完毕后会跳转到前一个input,左一不做任何处理if (index !== 0 && item.value === '') {self.$refs.ipInput[index - 1].focus();}} else if (e.keyCode === 13 || e.keyCode === 32 || e.keyCode === 190) {// 回车键、空格键、冒号均向右跳转,右一不做任何措施if (index !== 3) {self.$refs.ipInput[index + 1].focus();}} else if (item.value.toString().length === 3) {// 满3位,光标自动向下一个文本框if (index !== 3) {self.$refs.ipInput[index + 1].focus();}}},// 鼠标移入事件changeColor() {// 判断是否禁用(是否为已读),来显示边框if (this.disabled === false && this.readonly !== true) {this.actived = this.actived === 'actived' ? '' : 'actived';} else {this.actived = '';}}}};</script><style>.ami-input-ip{position: relative;width: 100%;.ipAdress{display: flex;border: 1px solid #dcdfe6;border-radius: 9px;padding-inline-start: 0px;//transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);li{position: relative;list-style-type: none;//表格样式.ipInputClass{.ami-input__inner{border: 0;width: 100%;padding: 0 10px;text-align: center;background: transparent;}}.ip-box{position: absolute;bottom: 8px;right: 0;border-radius: 50%;background: #505050;width: 2px;height: 2px;}}// 第三个点隐藏:last-child .ip-box{display: none;}}// 图标清空.icon{position:absolute;right: 3px;top:30%;font-size: 14px;}.actived{border: 1px solid $--input-focus-border;transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);}}</style>
3.说明文档
InputIp ip输入框
通过键盘输入ipv4地址。无法输入英文,数字大于255的自动转换
基础用法

v-model通过v-model来绑定数据
:::demo v-model通过v-model来绑定数据
<div style="width: 240px;"><ami-input-ip v-model="inputIp"></ami-input-ip></div><script>export default {data(){return{inputIp:"192.168.1.3"}}}</script>
:::
禁用状态

通过 disabled 属性指定是否禁用 ami-input-ip 组件
:::demo 通过 disabled 属性指定是否禁用 ami-input-ip 组件
<div style="width: 240px;"><ami-input-ip v-model="inputIp" disabled></ami-input-ip></div><script>export default {data(){return{inputIp:""}}}</script>
:::
只读

使用readonly属性即可得到一个只读的输入框
:::demo 使用readonly属性即可得到一个只读的输入框
<div style="width: 240px;"><ami-input-ip v-model="inputIp" readonly></ami-input-ip></div><script>export default {data(){return{inputIp:"192.168.0.1"}}}</script>
:::
尺寸

使用size属性即可控制输入框的大小, 支持输入默认和large、small、mini.
:::demo 使用size属性即可控制输入框的大小, 支持输入默认和large、small、mini.
<div style="width: 240px;"><ami-input-ip v-model="inputIp" size="large"></ami-input-ip></div><div style="width: 240px;"><ami-input-ip v-model="inputIp" size="small"></ami-input-ip></div><div style="width: 240px;"><ami-input-ip v-model="inputIp" size="mini"></ami-input-ip></div><script>export default {data(){return{inputIp:"192.168.0.1"}}}</script>
:::
返回格式

使用formatStyle属性即可控制返回值的格式, 支持输入node、noNode, 默认为node。node 返回格式为xxx.xxx.xxx.xxx, noNode返回格式为xxxxxxxxxxxx此格式不足字符用0填充。
:::demo
<div style="width: 240px"><ami-input-ip v-model="inputip"></ami-input-ip></div><span>返回值为:{{inputip}}</span><div style="width: 240px;margin-top:20px;"><ami-input-ip v-model="ipNoNode" :formatStyle="'noNode'"></ami-input-ip><span>返回值为:{{ipNoNode}}</span></div><script>export default {data(){return{inputip: '',ipNoNode: ''}}}</script>
:::
Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| v-model | 双向绑定(绑定数据) | String | — | 空 |
| disabled | 禁用(是否禁止编辑) | Boolean | true / false | false |
| readonly | 只读 | boolean | true / false | false |
| size | 输入框尺寸 | String | large / small / mini | — |
| formatStyle | 设置返回值类型 | String | node / noNode | node |
Input Events
| 事件说明 | 说明 | 回调参数 |
|---|---|---|
| clear | 在点击由 clearable 属性生成的清空按钮时触发(默认选中) | —— |
