IP 地址输入组件:基于 Vue.js 的可重用组件

在做设备管理平台时,涉及网络的界面经常要输入ip,可见在网络应用中,IP 地址的输入是一个非常常见的需求。为了以后不重复造轮子和提供更好的用户体验,我们可以创建一个可重用的 IP 地址输入组件。在本文中,我们将介绍如何使用 Vue.js 创建一个可重用的 IP 地址输入组件。

组件代码

以下是 IP 地址输入组件的代码:

vue 复制代码
<template>
  <div class="ip-input-container">
    <input v-for="(part, index) in ipParts" :key="index" ref="ipInput" v-model="ipParts[index]"
            @keydown="handleKeyDown(index, $event)" @input="handleInput(index, $event)" class="ip-input"
            :class="{ 'error': showError && !validateIP() }">
    <span v-if="showError" class="error-message">请输入有效的 IP 地址</span>
  </div>
</template>

<script>
export default {
    props: {
        value: String
    },
    data() {
        return {
            ipParts: ['', '', '', ''],
            inputValue: '',
            showError: false
        };
    },
    watch: {
        value(newVal) {
            console.log(newVal)
            this.inputValue = newVal;
            this.ipParts = ['', '', '', '']
            if (newVal) {
                this.ipParts = newVal.split('.');
            }
        },
        ipParts: {
            handler(newVal) {
                const ipString = newVal.join('.');
                if (ipString !== this.inputValue) {
                    this.inputValue = ipString;
                    this.$emit('input', ipString);
                }
            },
            deep: true
        }
    },
    mounted() {
        if (this.value) {
            this.inputValue = this.value;
            this.ipParts = this.value.split('.');
        }
    },
    methods: {
        handleKeyDown(index, event) {
            const input = event.target;
            const inputValue = input.value;

            if (event.key === "." && inputValue !== "") {
                const nextIndex = index + 1;
                if (nextIndex < this.ipParts.length) {
                    this.$refs.ipInput[nextIndex].focus();
                }
                event.preventDefault();
            } else if (
                event.key === "Backspace" &&
                inputValue === "" &&
                index > 0 &&
                input.selectionStart === 0
            ) {
                const prevIndex = index - 1;
                const prevInput = this.$refs.ipInput[prevIndex];
                prevInput.focus();
                prevInput.setSelectionRange(prevInput.value.length, prevInput.value.length);
                event.preventDefault();
            } else if (
                (event.key === "ArrowRight" ||
                    event.key === "Tab" ||
                    event.key === "Enter") &&
                index < this.ipParts.length - 1 &&
                input.selectionEnd === inputValue.length
            ) {
                const nextIndex = index + 1;
                setTimeout(() => {
                    this.$refs.ipInput[nextIndex].focus();
                }, 0);
                event.preventDefault();
            } else if (
                (event.key === "ArrowLeft" ||
                    event.key === "Shift" ||
                    (event.key === "Tab" && event.shiftKey)) &&
                index > 0 &&
                input.selectionStart === 0
            ) {
                const prevIndex = index - 1;
                const prevInput = this.$refs.ipInput[prevIndex];
                setTimeout(() => {
                    prevInput.focus();
                    prevInput.setSelectionRange(prevInput.value.length, prevInput.value.length);
                }, 0);
                event.preventDefault();
            }
        },
        handleInput(index, event) {
            let value = event.target.value;
            // 格式校验: 只允许输入数字
            value = value.replace(/[^\d]/g, '');
            // 截断超过3位的数字
            value = value.slice(0, 3);
            this.ipParts[index] = value;

            // 如果输入满了3个数字,自动跳转到下一个输入框
            if (value.length === 3 && index < this.ipParts.length - 1) {
                this.$refs.ipInput[index + 1].focus();
            }

            // 校验IP地址格式,并显示/隐藏错误提示
            this.showError = !this.validateIP();
            const ipString = this.ipParts.join('.');
            if (value || index === 3) {
                this.inputValue = ipString;
                this.$emit('input', ipString);
            }
        },
        validateIP() {
            const ipRegex = /^(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])){3}$/;
            const ipString = this.ipParts.join('.');
            return ipRegex.test(ipString);
        }
    }
};
</script>

<style scoped>
.ip-input-container {
    display: flex;
    height: 40px;
    padding-bottom: 10px;
}

.ip-input {
    width: 40px;
    text-align: center;
    border: none;
    border-bottom: 1px solid #ccc;
    margin-right: 5px;
    outline: none;
}

.ip-input.error {
    border-bottom-color: red;
}

.error-message {
    color: red;
}
</style>

组件说明

这个组件使用了 Vue.js 的 v-for 指令来渲染四个输入框,每个输入框都使用了 v-model 指令来绑定其值,并使用了 @keydown@input 事件来处理键盘事件和输入事件。组件还使用了 propswatch 来接收和监听父组件传递过来的 IP 地址。

组件使用示例

以下是 IP 地址输入组件的使用示例:

vue 复制代码
<template>
  <div>
    <h1>IP 地址输入组件示例</h1>
    <p>请输入一个有效的 IP 地址:</p>
    <ip-input v-model="ipAddress"></ip-input>
    <p>输入的 IP 地址是:{{ ipAddress }}</p>
  </div>
</template>

<script>
import IpInput from './IpInput';

export default {
  components: {
    IpInput
  },
  data() {
    return {
      ipAddress: ''
    };
  }
};
</script>

<style scoped>

</style>

在上面的示例中,我们首先导入了 IP 地址输入组件,然后在组件中使用了 v-model 指令来绑定输入的 IP 地址。当用户输入 IP 地址时,组件会实时更新 ipAddress 变量的值,并显示在页面上。

组件功能

IP 地址输入组件提供了以下功能:

  1. 自动分割 IP 地址:当用户输入 IP 地址时,组件会自动将其分割为四个部分,每个部分对应一个输入框。
  2. 格式校验:组件会实时校验用户输入的 IP 地址格式,并显示错误提示。
  3. 自动跳转:当用户输入完一个部分时,组件会自动跳转到下一个部分。
  4. 回退:当用户按下回退键时,组件会自动跳转到上一个部分。
  5. 键盘导航:用户可以使用 Tab 键和箭头键来导航到下一个和上一个部分。

总结

IP 地址输入组件是一个基于 Vue.js 的组件,用于输入和验证 IP 地址。它提供了实时的错误提示,并支持自动跳转到下一个输入框。我们可以通过 v-model 指令来绑定输入的 IP 地址,并实时获取输入的结果。这个组件可以帮助我们更快速、更方便地实现 IP 地址的输入和验证。若是觉得不完美,可以自己改下哈,毕竟我的追求就是能用就行。

相关推荐
GISer_Jing1 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪2 小时前
CSS复习
前端·css
咖啡の猫4 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5817 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路7 小时前
GeoTools 读取影像元数据
前端
ssshooter8 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal9 小时前
关于RSA和AES加密
前端·vue.js
柳杉9 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化