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

相关推荐
weixin_382395237 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__7 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.8 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~9 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华10 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子12 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅12 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni13 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学14 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端