likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 10

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

组件代码

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

<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 地址输入组件的使用示例:

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