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

相关推荐
CoolerWu8 小时前
TRAE SOLO实战成功展示&总结:一个所见即所得的笔记软体
前端·javascript
Cassie燁8 小时前
el-button源码解读1——为什么组件最外层套的是Vue内置组件Component
前端·vue.js
vx_bscxy3228 小时前
告别毕设焦虑!Python 爬虫 + Java 系统 + 数据大屏,含详细开发文档 基于web的图书管理系统74010 (上万套实战教程,赠送源码)
java·前端·课程设计
北极糊的狐8 小时前
Vue3 子组件修改父组件传递的对象并同步的方法汇总
前端·javascript·vue.js
spionbo8 小时前
Vue3 前端分页功能实现的技术方案及应用实例解析
前端
AI绘画小338 小时前
Web 安全核心真相:别太相信任何人!40 个漏洞挖掘实战清单,直接套用!
前端·数据库·测试工具·安全·web安全·网络安全·黑客
7***n758 小时前
前端设计模式详解
前端·设计模式·状态模式
用户47949283569158 小时前
Vite 中 SVG 404 的幕后黑手:你真的懂静态资源处理吗?
前端·vite
未来之窗软件服务9 小时前
幽冥大陆(三十五)S18酒店门锁SDK go语言——东方仙盟筑基期
java·前端·golang·智能门锁·仙盟创梦ide·东方仙盟·东方仙盟sdk
卸任9 小时前
解密Flex布局:为什么flex:1仍会导致内容溢出
前端·css·flexbox