vue实现IP地址输入框 前端vue3、vue2、react写IP输入框)

前端 ip地址框

在这里插入图片描述

用到了键盘监听事件 document.onkeydown 全局键盘监听
input 焦点出发 document.querySelector(‘#ip1’).focus()
下面是vue3语法,ant-design-vue 框架 react语法类似,主要里里面的方法复制走就好了

主要代码(vue2和vue3两种写法)

vue3语法

<template>
  <a-row>
    <a-col :span="14">
      <div class="ip-input">
        <input
          id="ip1"
          v-model="ipAddress.ip1"
          ref="input1"
          @input="handleInput(1)"
          @keydown="handleKeyDown($event, 1)"
          maxlength="3"
        />
        <span>.</span>
        <input
          id="ip2"
          v-model="ipAddress.ip2"
          ref="input2"
          @input="handleInput(2)"
          @keydown="handleKeyDown($event, 2)"
          maxlength="3"
        />
        <span>.</span>
        <input
          id="ip3"
          v-model="ipAddress.ip3"
          ref="input3"
          @input="handleInput(3)"
          @keydown="handleKeyDown($event, 3)"
          maxlength="3"
        />
        <span>.</span>
        <input
          id="ip4"
          v-model="ipAddress.ip4"
          ref="input4"
          @input="handleInput(4)"
          @keydown="handleKeyDown($event, 4)"
          @keyup.enter.native="saveOk"
          maxlength="3"
        />
      </div>
    </a-col>
    <a-col :span="10">
      <div style="line-height: 40px">
        &nbsp; &nbsp;<a-button @click="saveOk" type="primary">{{ $t('modal.ok') }}</a-button
        >&nbsp;
        <a-button @click="resetIp">{{ $t('fileSelect.reset') }}</a-button>
      </div>
    </a-col>
  </a-row>

  <br />
  <div style="color: #666"><sapn style="color: #f00">* </sapn>{{ $t('login.hostIpNote') }}</div>
</template>

<script lang="ts" setup>
import { message } from 'ant-design-vue';
import i18n from '/@/language';
import { onMounted, ref, reactive } from 'vue';

const IP_RULES =
  /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;

const props = defineProps({
  value: {
    type: String,
  },
});
const emit = defineEmits(['saveOk']);

const ipAddress: any = reactive({
  ip1: '',
  ip2: '',
  ip3: '',
  ip4: '',
});

onMounted(() => {
  const Store = require('electron-store');
  const store = new Store();
  let ipArr = store.get('serverAddressIp')?.split('.');
  if (ipArr) {
    ipAddress.ip1 = ipArr[0];
    ipAddress.ip2 = ipArr[1];
    ipAddress.ip3 = ipArr[2];
    ipAddress.ip4 = ipArr[3];
  }
});

const handleInput = (index: number) => {
  ipAddress[`ip${index}`] = ipAddress[`ip${index}`].replace(/[^0-9]/g, '');
  let ip = ipAddress[`ip${index}`];
  if (ip.length > 1 && ip[0] === '0') {
    ipAddress[`ip${index}`] = ip.slice(1);
  }
  if (ip > 255) {
    ipAddress[`ip${index}`] = '255';
  }
  if (ip.length === 3 || ip[0] === '0') {
    let nextIndex = index + 1;
    if (nextIndex <= 4) {
      document.querySelector(`#ip${nextIndex}`).focus();
    }
  }
};

const handleKeyDown = (event: any, index: number) => {
  let ip = ipAddress[`ip${index}`];
  if (event.keyCode == 8 && 0 == document.getElementById(`ip${index}`).selectionStart) {
    let nextIndex = index - 1;
    if (nextIndex >= 1) {
      console.log(nextIndex);

      document.querySelector(`#ip${nextIndex}`).focus();

      document
        .getElementById(`ip${nextIndex}`)
        .setSelectionRange(ipAddress[`ip${nextIndex}`].length, ipAddress[`ip${nextIndex}`].length);
    }
  } else if (
    event.keyCode == 46 &&
    ip.length == document.getElementById(`ip${index}`).selectionStart
  ) {
    let nextIndex = index + 1;
    if (nextIndex <= 4) {
      document.querySelector(`#ip${nextIndex}`).focus();

      document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
    }
  } else if (event.keyCode == 37 && 0 == document.getElementById(`ip${index}`).selectionStart) {
    let nextIndex = index - 1;
    if (nextIndex >= 1) {
      document.querySelector(`#ip${nextIndex}`).focus();

      document
        .getElementById(`ip${nextIndex}`)
        .setSelectionRange(ipAddress[`ip${nextIndex}`].length, ipAddress[`ip${nextIndex}`].length);
    }
  } else if (
    event.keyCode == 39 &&
    ip.length == document.getElementById(`ip${index}`).selectionStart
  ) {
    let nextIndex = index + 1;
    if (nextIndex <= 4) {
      document.querySelector(`#ip${nextIndex}`).focus();

      document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
    }
  } else if (event.keyCode == 110 || event.keyCode == 190) {
    let nextIndex = index + 1;
    if (nextIndex <= 4) {
      document.querySelector(`#ip${nextIndex}`).focus();
    }
  } else {
    return false;
  }
};
const saveOk = () => {
  if (ipAddress.ip1 == '' || ipAddress.ip2 == '' || ipAddress.ip3 == '' || ipAddress.ip4 == '') {
    message.warning(i18n.global.t('login.ipRules'));
  } else {
    console.log('ip');
    const ip = ipAddress.ip1 + '.' + ipAddress.ip2 + '.' + ipAddress.ip3 + '.' + ipAddress.ip4;
    emit('saveOk', ip, IP_RULES.test(ip));
  }
};
const resetIp = () => {
  ipAddress.ip1 = '';
  ipAddress.ip2 = '';
  ipAddress.ip3 = '';
  ipAddress.ip4 = '';
};
</script>

<style scoped>
.ip-input {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 40px;
  /* border: 1px solid #ccc; */
  border: 1px solid #204fc7;

  border-radius: 4px;
  padding: 0 10px;
  box-sizing: border-box;
  font-size: 16px;
}

.ip-input input {
  width: 40px;
  height: 90%;
  border: none;
  outline: none;
  text-align: center;
  font-size: 16px;
}

.ip-input span {
  font-size: 16px;
}
</style>


vue2语法

<template>
  <a-row>
    <a-col :span="14">
      <div class="ip-input">
        <input
          id="ip1"
          v-model="ip1"
          ref="input1"
          @input="handleInput(1)"
          @keydown="handleKeyDown($event, 1)"
          maxlength="3"
        />
        <span>.</span>
        <input
          id="ip2"
          v-model="ip2"
          ref="input2"
          @input="handleInput(2)"
          @keydown="handleKeyDown($event, 2)"
          maxlength="3"
        />
        <span>.</span>
        <input
          id="ip3"
          v-model="ip3"
          ref="input3"
          @input="handleInput(3)"
          @keydown="handleKeyDown($event, 3)"
          maxlength="3"
        />
        <span>.</span>
        <input
          id="ip4"
          v-model="ip4"
          ref="input4"
          @input="handleInput(4)"
          @keydown="handleKeyDown($event, 4)"
          @keyup.enter.native="saveOk"

          maxlength="3"
        />
      </div>
    </a-col>
    <a-col :span="10">
      <div style="line-height: 40px;">
        &nbsp; &nbsp;<a-button @click="saveOk" type="primary">{{ $t('modal.ok') }}</a-button
        >&nbsp;
        <a-button @click="resetIp">{{ $t('fileSelect.reset') }}</a-button>
      </div>  
    </a-col>
  </a-row>

  <br />
  <div style="color: #666"><sapn style="color: #f00">* </sapn>{{ $t('login.hostIpNote') }}</div>
</template>

<script>
import { message } from 'ant-design-vue';
import i18n from '/@/language';

const IP_RULES =
  /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;

export default {
  name: 'IpModel',
  props: {
    IP: String,
  },
  data() {
    return {
      ip1: '',
      ip2: '',
      ip3: '',
      ip4: '',
    };
  },
  created() {
    const Store = require('electron-store');
    const store = new Store();
    let ipArr = store.get('serverAddressIp')?.split('.');
    if (ipArr) {
      this.ip1 = ipArr[0];
      this.ip2 = ipArr[1];
      this.ip3 = ipArr[2];
      this.ip4 = ipArr[3];
    }
  },
  methods: {
    handleInput(index) {
      this[`ip${index}`] = this[`ip${index}`].replace(/[^0-9]/g, '');
      let ip = this[`ip${index}`];
      if (ip.length > 1 && ip[0] === '0') {
        this[`ip${index}`] = ip.slice(1);
      }
      if (ip > 255) {
        this[`ip${index}`] = '255';
      }
      if (ip.length === 3 || ip[0] === '0') {
        let nextIndex = index + 1;
        if (nextIndex <= 4) {
          this.$refs[`input${nextIndex}`].focus();
        }
      }
    },
    handleKeyDown(event, index) {
      let ip = this[`ip${index}`];
      if (event.keyCode == 8 && 0 == document.getElementById(`ip${index}`).selectionStart) {
        let nextIndex = index - 1;
        if (nextIndex >= 1) {
          this.$refs[`input${nextIndex}`].focus();
          document
            .getElementById(`ip${nextIndex}`)
            .setSelectionRange(this[`ip${nextIndex}`].length, this[`ip${nextIndex}`].length);
        }
      } else if (
        event.keyCode == 46 &&
        ip.length == document.getElementById(`ip${index}`).selectionStart
      ) {
        let nextIndex = index + 1;
        if (nextIndex <= 4) {
          this.$refs[`input${nextIndex}`].focus();
          document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
        }
      } else if (event.keyCode == 37 && 0 == document.getElementById(`ip${index}`).selectionStart) {
        let nextIndex = index - 1;
        if (nextIndex >= 1) {
          this.$refs[`input${nextIndex}`].focus();
          document
            .getElementById(`ip${nextIndex}`)
            .setSelectionRange(this[`ip${nextIndex}`].length, this[`ip${nextIndex}`].length);
        }
      } else if (
        event.keyCode == 39 &&
        ip.length == document.getElementById(`ip${index}`).selectionStart
      ) {
        let nextIndex = index + 1;
        if (nextIndex <= 4) {
          this.$refs[`input${nextIndex}`].focus();
          document.getElementById(`ip${nextIndex}`).setSelectionRange(0, 0);
        }
      } else if (event.keyCode == 110 || event.keyCode == 190) {
        let nextIndex = index + 1;
        if (nextIndex <= 4) {
          this.$refs[`input${nextIndex}`].focus();
        }
      } else {
        return false;
      }
    },
    saveOk() {
      if (this.ip1 == '' || this.ip2 == '' || this.ip3 == '' || this.ip4 == '') {
        message.warning(i18n.global.t('login.ipRules'));
      } else {
        console.log('ip');
        const ip = this.ip1 + '.' + this.ip2 + '.' + this.ip3 + '.' + this.ip4;

        this.$emit('saveOk', ip, IP_RULES.test(ip));

        // this.$emit('changeIP', ip);
      }
    },
    IpModelCancel() {
      this.ip1 = this.IP.split('.')[0];
      this.ip2 = this.IP.split('.')[1];
      this.ip3 = this.IP.split('.')[2];
      this.ip4 = this.IP.split('.')[3];
    },
    resetIp() {
      this.ip1 = '';
      this.ip2 = '';
      this.ip3 = '';
      this.ip4 = '';
    },
  },
};
</script>

<style scoped>
.ip-input {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 40px;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 0 10px;
  box-sizing: border-box;
  font-size: 16px;
}

.ip-input input {
  width: 40px;
  height: 90%;
  border: none;
  outline: none;
  text-align: center;
  font-size: 16px;
}

.ip-input span {
  font-size: 16px;
}
</style>

引用

在这里插入图片描述

<template>
  <a-modal
    :visible="identifying.IpVisible"
    :title="$t('login.hostIp')"
    width="445px"
    @cancel="() => (identifying.IpVisible = false)"
    zIndex="1"
    :footer="null"
  >
    <a-form-item label="">
      <ipInputVue3 @cancel="() => (identifying.IpVisible = false)" @saveOk="saveIp" />
    </a-form-item>
  </a-modal>
</template>

<script lang="ts" setup>
import { onMounted, reactive, watch } from 'vue';
import { message } from 'ant-design-vue';
import ipInputVue3 from '/@/components/ip/index.vue';

const props = defineProps({
  value: {
    type: String,
    default: '',
  },
});

const identifying = reactive({
  IpVisible: false,
});
onMounted(() => {});

const saveIp = (ipAddress: string, isRight: Boolean) => {
  console.log(ipAddress);

  if (isRight) {
    message.warning('ip格式正确,继续操作');
   
  } else {
    message.warning('ip格式不正确');
  }
};
</script>

<style lang="less" scoped></style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
回答: ReactVue是两个流行的前端框架,它们在一些方面有一些区别。React整体的思路是函数式的,推崇纯组件、数据不可变和单向数据流。而Vue是基于可变数据的,支持双向绑定。React的组件扩展一般通过高阶组件实现,而Vue使用mixin。React的功能相对较少,很多功能是由社区完成的,而Vue内置了很多功能,使得开发更加方便。例如,React需要使用Redux来管理状态,而Vue内置了Vuex来管理状态。此外,React使用Virtual DOM来提高性能,而Vue不需要使用Immutable来优化性能。关于ReactVue2和Vue3的区别,我没有找到相关的引用内容。但是可以说,Vue3相对于Vue2有一些重要的改进,包括更好的性能、更小的包体积、更好的TypeScript支持等。Vue3还引入了Composition API,使得组件的逻辑更加灵活和可复用。总的来说,ReactVue都是优秀的前端框架,选择哪个取决于个人的偏好和项目需求。 #### 引用[.reference_title] - *1* *2* [Reactvue的区别](https://blog.csdn.net/weixin_45785651/article/details/121556598)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [ReactVue的区别](https://blog.csdn.net/PILIpilipala/article/details/118298282)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜空孤狼啸

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值