來重構吧-vue
上一次製作出來的元件,感謝哈囉的建議讓我的code可以更精簡。
所以我們就來動手重構吧!
重構分了幾個步驟
在原本的寫法裡,運用大量的props以及emits來做父子之間的溝通,看起來會格外的笨重。
因此簡化成,input元件只會做接收props的顯示不做其他事情。
//component
<script setup>
import { defineProps } from "vue";
defineProps({
name: Number,
});
</script>
<template>
<input
type="text"
class="h-full w-full rounded-md border border-gray-300 p-1 text-center md:w-20"
maxlength="3"
:name="name"
/>
</template>
//parent
<div class="flex space-x-3" v-for="index in 4" :key="index">
<IpsetInput :name="index - 1" />
<label v-if="index !== 4" class="self-end">.</label>
</div>
原本我們利用了vue的 watch來做每個v-model的監聽,不過其實在input產生變化時去判斷target也就不用每一個input切出一個v-model去做監聽看起來很冗長。
在這裏我們首先利用了vue的一個method來監聽input行為。
@input="onChange"
在這個onChange的function,首先我們取得我們想知道的幾個值,就是他的value,長度maxlength以及name。
function onChange(e) {
const { value, maxLength, name } = e.target;
}
接著,因為我們希望是在input的位數到達最大位數三位的時候做判斷,所以要是沒有達到這個長度的值我們就不會去做特別處理。
function onChange(e) {
const { value, maxLength, name } = e.target;
if (value.length !== maxLength && value.length !== 0) return;
}
接著我們一樣想要操控DOM來讓我們輸入可以自動跳至下一個input或者在減少的時候跳回前一個input。
在這裡我們先抓到form這個element,使用的是 .closest() 這個方法,他可以抓到最接近你本身然後符合條件的element。
function onChange(e) {
const { value, maxLength, name } = e.target;
if (value.length !== maxLength && value.length !== 0) return;
const form = e.target.closest("form");
}
再來我們找到目前所在的是第幾個input,先前我們利用了name作為索引。
function onChange(e) {
const { value, maxLength, name } = e.target;
if (value.length !== maxLength && value.length !== 0) return;
const form = e.target.closest("form");
const current = Number(name);
}
</script>
接著判斷如何去跳轉input,這邊因為還要包含跳回前一個,所以我這邊做了一個自己的方法。
if (value.length === 0) {
if (current - 1 >= 0)
form.querySelector(`input[name="${current - 1}"]`)?.focus();
return;
}
form.querySelector(`input[name="${current + 1}"]`)?.focus();
想法是,當input不是空的時候就會跳到下一個,當是空得時候判斷他是否是第一個假如是的話不做事情,不然就會退回前一個。
原本是使用比較暴力的去判斷他是否是數字以及在0-255之間,不過在哈囉的建議下才發現最好用的是正規表達去判斷,這邊我找到了一個判斷ip address的正規表達式(還是不會自己寫出來QAQ)
function isValidateIP(val) {
return /(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}/.test(
val
);
}
那麼在驗證之前,先來把四個input結合成一個ip位址吧!
這邊就利用formdata來處理收到的input。
首先去建立一個FormData並且把他整理成一個只有input值的Object
function toFormData(form) {
return Object.fromEntries(new FormData(form).entries());
}
這個方法很好用!出來的會是一個Object
{0: '', 1: '', 2: '', 3: ''}
接著就能把他組成一個array然後變成我們要的ip address的 string
function onSubmit(e) {
const ip = Array.from({ ...toFormData(e.target), length: 4 }).join(".");
isError.value = !isValidateIP(ip);
}
這樣的ip就會是
簡直太棒拉!
這樣我們就能用已經設定好的驗證function就完成了呀!
function onSubmit(e) {
const ip = Array.from({ ...toFormData(e.target), length: 4 }).join(".");
isError.value = !isValidateIP(ip);
}