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 地址的输入和验证。若是觉得不完美,可以自己改下哈,毕竟我的追求就是能用就行。

相关推荐
修己xj13 分钟前
告别手动存图!这款叫 Fatkun 的浏览器插件,简直是素材收集神器
前端
袋鼠云数栈1 小时前
从前端到基础设施,ACOS 如何打通企业全链路可观测
运维·前端·人工智能·数据治理·数据智能
AskHarries1 小时前
系统提示词、开发者指令和用户输入的优先级
java·前端·数据库
Moment1 小时前
长上下文会最终杀死 Rag 吗?
前端·javascript·后端
qcx232 小时前
【系统学AI】25 论文导读 ①:两篇改变 AI 的开山之作——Attention Is All You Need & ReAct
前端·人工智能·react.js·transformer
kyriewen3 小时前
大文件上传最全指南:分片、断点续传、秒传,一篇就够了
前端·javascript·面试
郑洁文3 小时前
基于Python的Web命令执行漏洞自动化检测系统
前端·python·网络安全·自动化
新酱爱学习4 小时前
手搓 10 个 Skill 后,我把重复劳动收敛成了一套零依赖 CLI 工具
前端·javascript·人工智能
IT_陈寒4 小时前
Python的线程池居然把我坑在了垃圾回收这块
前端·人工智能·后端
研☆香4 小时前
es6新特性功能介绍(一)
前端·ecmascript·es6