【React hook】手把手學會 Form 表單驗證與 UX 優化全教學

更新於 發佈於 閱讀時間約 31 分鐘
Snapshot from project example
在開發 React 時,就發現表格其實是整個網站當中,最常擁有複雜邏輯或驗證的地方。通常表格也會和許多狀態相關,也因此讓設計變得更為複雜。今天這篇文章,就帶大家不使用第三方套件如 Formik,手把手帶你刻 React 的表單驗證。
這篇文章,總共會提到下面三個主題:
  1. 為什麼表單驗證很重要?
  2. 表單驗證的三階段?
  3. 如何優化表單設計?
筆者也會在下面,逐步說明每一個步驟的概念,就讓我們開始吧!

為什麼表單驗證很重要?

在開發前端網頁時,表單是整個開發過程中,非常重要的一塊。因為表單,通常是使用者互動最多的部分,也最容易遇到各種邏輯問題。例如:
  1. 資料型態可能不符合
  2. 需要在使用者輸入錯誤時,提示錯誤並協助更新狀態
  3. 使用者上傳錯誤資訊,導致 Server 收到錯誤資料
甚至在輸入後,也需要進一步至資料庫驗證,還會需要考慮驗證的時間點。例如使用者名稱確認,上述這些情境,都是導致 Form 困難的原因。
也因此,要讓使用者在輸入時,不需額外花費精力理解,但又能讓使用者在輸入錯誤資料時,第一時間獲得反饋,讓使用者有機會,能即時更正輸入的資訊。

前端在表單驗證的角色

對於資料驗證來說,除了在前端進行資料驗證外,也需要在後端進行驗證。主要的原因,是因為前端是能讓使用者透過修改原始碼,讓驗證失效。有興趣的朋友可以參考 Hide JavaScript Code 這篇文章
因此,前端在本身的機制上,無法保證資料的正確性和安全性。

表單驗證的三階段

表單設計 Flow
在分析表單驗證時,主要會分成三個階段,分別是:
  1. 當使用者輸入時
  2. 當表格 lost focus 時
  3. 當表格被 Submit 時
每一個部分,都會有各自所遇到的議題,以下是各自常見的議題:
  1. Input:當使用者在輸入時,需要至少讓使用者有輸入正確的時間點。並要在確認輸入資訊無效時,才提供錯誤 feedback。
  2. Lost Focus:我們預設使用者會輸入正確資訊,真的錯誤才提醒。對於應用在未被編輯的表單時,非常有效。
  3. Submit:資料格式可能錯誤,但我們需要在使用者 Submit 後,才根據他的答案提示錯誤;但帶來的缺點,就是 feedback 太晚。
接著,就讓我們一步一步看下去吧!

一、當使用者輸入時

Snapshot from project example

A. 如何獲取使用者的輸入內容?

獲取使用者在 Input 的輸入內容,是整個表單驗證的核心。因此也將這個步驟,放在第一個階段。要獲取使用者的輸入內容,主要有兩個方式:
  1. 使用 Event handler 抓取資料
  2. 使用 useRef 獲取 DOM 資料
上述兩個方式,各自帶來的優缺點分別為是:
  1. 使用 Event Handler:優點是能夠做到更細緻的資料驗證,能夠即時給予使用者輸入回饋。但部分情境不需要追蹤每一個輸入值,會導致無意義的重渲染。
  2. 使用 useRef:能夠精簡地獲得資料驗證,但通常僅會使用在上傳(Submit)資料時。因為他需要 Callback,才能觸發當時在 DOM 上的資料狀態;缺點則是無法做到較細緻即時輸入驗證。

1.Event Handler 的寫法

在使用之前,需要提醒每一次修改 Input,例如輸入或刪除,都會觸發 React 元件的 re-render。在下列步驟中,利用每一次改變 Input 值時,會呼叫 Input 屬性的 onChange,讓新的值能夠更新至 enteredInput。
具體步驟如下:
  1. 使用 Handler 抓取當前的 event
  2. 使用 event.target.value 抓到 input 的值
  3. 使用 setEnteredInput 更新輸入值
  4. 將 enteredInput 使用於資料驗證
const [enteredInput, setEnteredInput] = useState("");
const submitHandler = (event) => {
  // submit data...
};
const inputChangeHandler = (event) => {
  setEnteredInput(event.target.value);
};
<form onSubmit={submitHandler}>
  <label htmlFor="name">Your Name</label>
  <input type="text" id="name" onChange={inputChangeHandler} />
</form>
其中,label 的屬性 htmlFor,會自動指向相同 id 的 input。因此若點擊 Label 的字,就會自動 Focus name 這個 Input。

2.useRef 的寫法

useRef 的概念更像是快照(snapshot),在特定 Callback 被呼叫時,就可以擷取被 useRef 監聽的元件。而 useRef 會擷取整個被監聽元件的 DOM,也因此可以獲取其中的 value。
具體步驟如下:
  1. 使用 useRef 設定監聽器
  2. 將監聽器傳入 Input 的屬性 ref
  3. 在 Submit 時使用監聽到的資料 inputRef
  4. 從 inputRef.current.value 獲取 Input 的值
const inputRef = useRef();
const submitHandler = (event) => {
  submitDataHandler(inputRef.current.value);
};
return (
  <form onSubmit={submitHandler}>
    <label htmlFor="name">Your Name</label>
    <input type="text" id="name" ref={inputRef} />
  </form>
);

二、當表格 Lost focus 時

Snapshot from project example
當使用者輸入完表格,準備離開當前輸入框時,就可以做第一次的驗證,可以避免使用者最後一刻,才收到修改的提示或無法提交。
要執行 Lost Focus 時的驗證,需要有四個步驟:
  1. 檢驗輸入資料的正確性
  2. 檢驗表格是否輸入過
  3. 顯示錯誤提示訊息
  4. 即時驗證與更新訊息

A. 檢驗輸入資料的正確性

最常見的莫過於姓名與 Email 的驗證,以下簡單提供驗證的方式,當然直接請 ChatGPT 協助你寫正規表達式,整體的速度會更快。
這個階段,是確保從 state 抓到的資料,可以明確知道當前的資料是否符合驗證,若符合驗證,就可以提交;若不符合驗證,就會跳出修改的提示訊息。

為空值 input 進行驗證

透過 trim 去掉頭尾的空白,並確保長度大於 0。
const nameValidation = (name) => {
  const isNameInputValid = name.trim().length !== 0;
  return isNameInputValid;
};

為 Email 進行驗證:

const emailValidation = (email) => {
  const re = /^(([^<>()\\[\\]\\\\.,;:\\s@"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;
  return re.test(String(email).toLowerCase());
}

B. 檢驗表格是否曾輸入過

除了驗證資料是否正確外,另一個重點,就是確認使用者是否碰觸過輸入框。因此,我們就需要用到 DOM 提供的內建方法 onBlur,來監測當使用者 Lost Focus 時,需要執行的 callback function。
const [enteredNameInput, setEnteredNameInput] = useState("");
const [isNameInputTouched, setIsNameInputTouched] = useState(false);
// DEFINE Callback function
const inputNameBlurHandler = (event) => {
    setIsNameInputTouched(true);
  };
// CALLBACK WHEN INPUT LOST FOCUS
<input onBlur={inputBlurHandler} />

C. 顯示錯誤提示訊息

接著,我們就要使用前面提到的驗證資料正確性,以及確認表格是否被輸入過,卻評估是否需要顯示錯誤訊息。
以下,我們就拿名稱輸入的表格,進行錯誤訊息的提示示範。而錯誤訊息之所以要使用 isNameInputTouched!isNameInputValid (意指驗證無效),是因為我們相信使用者,「一開始是會輸入正確資訊」,所以當 Touched 被預設為 false 時,就不會出現 Error。
直到使用者確定有 Lost Focus 的行為,但卻又沒有通過驗證時,再顯示錯誤訊息才適合適的時機。
假設我們是使用者,也不希望一開始,就被通知輸入無效資訊吧!

使用 CSS Class,控制錯誤訊息顯示

// VALIDATE nameInput is INVALID
const nameInputIsInvalid = isNameInputTouched && !isNameInputValid;
// SET INPUT CLASS WITH ERROR STATE
const nameInputClass = nameInputIsInvalid
    ? "form-control invalid"
    : "form-control";
// DISPLAY error message WHEN INPUT IS INVALID
<div className={nameInputClass}>
  <label htmlFor="name">Your Name</label>
  <input
    value={enteredNameInput}
    type="text"
    id="name"
    onBlur={inputNameBlurHandler}
    onChange={inputNameChangeHandler}
  />
  {nameInputIsInvalid && <p className="error-text">Name must not be empty.</p>}
</div>;

D. 即時驗證與更新訊息

當使用者更正為正確內容時,只要一符合標準,我們就將 Error Message 移除。讓使用者知道,他已經正確達到要求。
這裡要再重新強調一個概念,每當我們使用 Event Listener 監控 Input 的值時,每一次觸發 Callback function,都會讓整個元件重新渲染。因此,在第三階段的「顯示錯誤提示訊息」中,nameInputIsInvalid 每一次都會重新聲明,因此每鍵入一次,就會重新驗證一次。也因此 nameInputIsInvalid 的值,也都會根據每一次輸入,而重新驗證。
除此之外,我們也能夠透過狀態管理,讓整個表格的遞交按鈕,能夠暫時被關閉。

利用驗證,暫時關閉提交(Submit)按鈕

Snapshot from project example
以下就以 Email 和名稱的表格驗證,來示範如何達成。我們先個別設定 Email 和名稱的 Input 的 touched 狀態;接著,撰寫 Email 和名稱的驗證;再來,個別驗證輸入的有效性。最後,才是驗證整個表格的狀態。
const [enteredEmailInput, setEnteredEmailInput] = useState("");
const [isEmailInputTouched, setIsEmailInputTouched] = useState(false);
const [enteredNameInput, setEnteredNameInput] = useState("");
const [isNameInputTouched, setIsNameInputTouched] = useState(false);
const checkEmail = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
const isEmailInputValid = checkEmail.test(enteredEmailInput);
const isNameInputValid = enteredNameInput.trim().length !== 0;
const nameInputIsInvalid = isNameInputTouched && !isNameInputValid;
const emailInputIsInvalid = isEmailInputTouched && !isEmailInputValid;
// APPLY FOR MANAGING BUTTON STATUS
const isFormValid = isNameInputValid && isEmailInputValid;
// JSX SUBMIT BUTTON
<div className="form-actions">
  <button disabled={!isFormValid}>Submit</button>
</div>;

三、當表格被 Submit 時

Snapshot from project example
當使用者輸入完表格(或輸入錯誤的資訊時),仍然要在遞交時,再進行一次 Submit,確保推去後端的資料沒問題。
要執行 Submit 驗證時,有兩個步驟需要被考慮到:
  1. 多表格驗證
  2. 重置表格

A. 多表格驗證

若我們有在前面階段,就使用多表格的確認,就可以同樣在 Submit 時,使用表格驗證來做最後一層確認。我們使用上一個「暫時關閉提交按鈕」的案例來延伸。我們可以在處理提交的 SubmitHandler 中,使用判斷式來決定,是否要執行此次的 Submit 行為。
const submitHandler = (event) => {
  event.preventDefault();
  // DEFAULT USER HAS TOUCHED INPUT DUE TO CONFIRMATION
  setIsFormTouched(true);
  // COULD NOT SUBMIT IF FORM IS NOT VALID
  if (!isFormValid) {
    // DROP OUT DUE TO return
    return;
  }
  fetch(url, { method: "POST", body: ...})
};
其中,我們先使用 event.preventDefault();,來避免 Submit 後會重新 Reload 畫面的預設狀態。接著,為了讓錯誤能跳轉出來,此處我們將 setIsFormTouched 設定為 true,可以視為用戶已經完成編輯,因此一定會接觸過表格。
再來,就是使用一個簡單的判斷式 !isFormValid,來確定表單已經完成驗證,若沒有,就會直接跳出函式,後面的 fetch 遞交也就不會執行。

B. 重置表格

有時我們希望輸入後,表格可以重置,讓使用者可以繼續輸入下一次的內容。這時可以使用兩個方式:
  1. 重置 State
  2. 操控 useRef
以下個別示範各自的用法。
1.重置 State
// STATE UPDATE
const [enteredInput, setEnteredInput] = useState("");
const [isFormTouched, setIsFormTouched] = useState("");
const submitHandler = (event) => {
  event.preventDefault();
  ...
  setEnteredInput("");
  setIsFormTouched(false);
};
<input value={enteredInput} />
2.操控 useRef
// useRef UPDATE | NOT RECOMMAND!
const [isFormTouched, setIsFormTouched] = useState("");
const inputRef = useRef();
const submitHandler = (event) => {
  event.preventDefault();
  inputRef.current.value = "";
  setIsFormTouched(false);
};
<input ref={inputRef} />
第二個方式,是使用 useRef 時,又需要重置 Input 的值時使用。因為會直接操縱到 DOM,因此通常不建議如此使用。如果有重置 Input 的需求,還是盡量使用 useState 進行更新。

優化表單設計

前面敘述的寫法,如果超過一個表格時,就會發現重複的程式碼非常多;更麻煩的是,會讓個別元件變得肥大。試想,如果上述的程式碼需要檢驗 7~8 個表格,雖然結構簡單且易懂,但就容易讓程式碼變得冗長。
因此,若要優化整個元件設計,有兩個常見的改善方式:
  1. 拆分個別元件
  2. 使用 Custom hook
  3. 使用第三方套件

A. 拆分個別元件

這個概念也非常直觀,我們僅需要將每一個 Input 都轉換成一個獨立的元件,並在各自的元件中進行驗證即可。
然而,這個架構會導致一個問題:在進行完整全表單的驗證時,就需要將各自的參數全部傳出,這會導致父層元件多了非常多參數傳遞。
這個方式僅建議使用在 2~3 個 Input 時使用。

B. 使用 Custom hook

一開始的時候,確實很難判斷是否要使用 custom hook,但在開始後發現有重複的地方,就可以考慮重新使用 custom hook 來抽象化。
透過抽離所有重複的程式碼,我們也將原先特定的 nameInput 等,調整成 enteredValue 這樣通用的變數。
// in src/hooks/use-input.js
import { useState } from "react";
// MUST start with "use"
const useInput = (validationFunc) => {
  const [enteredValue, setEnteredValue] = useState("");
  const [isTouched, setIsTouched] = useState(false);
  const isValueValid = validationFunc(enteredValue);
  const hasError = isTouched && !isValueValid; // false and true
  const valueChangeHandler = (event) => {
    setEnteredValue(event.target.value);
  };
  const valueBlurHandler = (event) => {
    setIsTouched(true);
  };
  const resetValueHandler = () => {
    setEnteredValue("");
    setIsTouched(false);
  };
  const inputClassHandler = () => {
    const className = hasError ? "form-control invalid" : "form-control";
    return className;
  };
  return {
    value: enteredValue,
    hasError: hasError,
    isValueValid: isValueValid,
    inputClass: inputClassHandler(),
    reset: resetValueHandler,
    valueChangeHandler,
    valueBlurHandler,
  };
};
export default useInput;

Custom hook 實際案例應用:

在我們欲使用表單的元件中,引入 custom hook 來生成表單驗證。此處,我們使用了 name 和 email 這兩個 Input,設計一張表單來驗證。
透過傳入 validation function,我們可以輕易生成個別表單的各種狀態。透過生成的狀態,就可以在想要管理的 Input 中,傳入各種所需的參數。
import useInput from "../hooks/use-input";
const SimpleForm = (props) => {
  const emailValidation = (email) => {
    const checkEmailRegExp = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
    const isEmailInputValid = checkEmailRegExp.test(email);
    return isEmailInputValid;
  };
  const nameValidation = (name) => {
    const isNameInputValid = name.trim().length !== 0;
    return isNameInputValid;
  };
  const {
    value: emailInput,
    hasError: emailInputHasError,
    isValueValid: isEmailInputValid,
    inputClass: emailInputClass,
    reset: resetEmailInput,
    valueChangeHandler: emailInputChangeHandler,
    valueBlurHandler: emailInputBlurHandler,
  } = useInput(emailValidation);
  const {
    value: nameInput,
    hasError: nameInputHasError,
    isValueValid: isNameInputValid,
    inputClass: nameInputClass,
    reset: resetNameInput,
    valueChangeHandler: nameInputChangeHandler,
    valueBlurHandler: nameInputBlurHandler,
  } = useInput(nameValidation);
  // IF INPUT HAS ERROR, THEN SET BUTTON DISABLE
  const isFormValid = !nameInputHasError && !emailInputHasError;
  const submitHandler = (event) => {
    event.preventDefault();
    // CHECK WHETHER EITHER INPUT IS INVALID, THEN DROPOUT
    if (!isNameInputValid || !isEmailInputValid) {
      return;
    }
    resetEmailInput();
    resetNameInput();
    console.log(emailInput);
    console.log(nameInput);
  };
  return (
    <form onSubmit={submitHandler}>
      <div className={emailInputClass}>
        <label htmlFor="email">Your Email</label>
        <input
          value={emailInput}
          type="email"
          id="email"
          onBlur={emailInputBlurHandler}
          onChange={emailInputChangeHandler}
        />
        {emailInputHasError && (
          <p className="error-text">Email format is not allowed.</p>
        )}
      </div>
      <div className={nameInputClass}>
        <label htmlFor="name">Your Name</label>
        <input
          value={nameInput}
          type="text"
          id="name"
          onBlur={nameInputBlurHandler}
          onChange={nameInputChangeHandler}
        />
        {nameInputHasError && (
          <p className="error-text">Name must not be empty.</p>
        )}
      </div>
      <div className="form-actions">
        <button disabled={!isFormValid}>Submit</button>
      </div>
    </form>
  );
};

C.使用第三方套件

除了自己實現表單驗證外,也有設計好的套件可以使用。例如 React 生態系所使用的 Formik,就是一個很完善的表單套件。可以根據自己的需求取用。

結論

表單設計,一直是前端處理很複雜的一塊;但複雜的並非程式,而是在輸入表單時,能否給予使用者完整、友善的體驗,更讓使用者知道,要如何更改輸入才能通過驗證。
因此在設計表單時,除了確認資料的驗證外,瞭解使用者的輸入習慣,甚至要考量到極端情境或資安問題,才能讓使用者在滿足個人的使用需求外,不需要擔心個人的資料被竊取。
若有有興趣或相關經驗的讀者,也歡迎留言一起分享交流!

參考資料

為什麼會看到廣告
此處作為整理前端(Frontend)和相關的 HTML、CSS、JavaScript、React 等前端觀念與技巧,全部都會收錄在這個專題之中。同時也會將相關的技術與反思記錄在此,歡迎各位讀者互相交流。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
useContext 是一種 React hook,讓我們能夠直接取用其他元件的 Context,而無須層層傳遞 props,進而使程式碼簡潔易讀。
在傳統開發的過程中,很容易會搞混一般的 this 和箭頭函式(arrow function)中的 lexcial "this" 兩者的差異。本文就以實際的例子來說明各自的差異,以及在未來使用時需要注意哪一些細節。
useContext 是一種 React hook,讓我們能夠直接取用其他元件的 Context,而無須層層傳遞 props,進而使程式碼簡潔易讀。
在傳統開發的過程中,很容易會搞混一般的 this 和箭頭函式(arrow function)中的 lexcial "this" 兩者的差異。本文就以實際的例子來說明各自的差異,以及在未來使用時需要注意哪一些細節。
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
本文介紹瞭如何在後端系統開發時設計不同表單的簽核流程,包括請假表單和採購表單。以及如何動態生成簽核表單,並建立簽核節點。另外還介紹瞭如何利用繼承來簡化簽核流程的設定。
Thumbnail
這邊統整了過往喜特先生發布過的「資料驗證」系列文! 資料驗證是個「驗證資料是否符合某條件的機制」,我們通常會用它來避免別人輸入無效的值,減少錯誤的發生。你可以按照順序慢慢學習,把資料驗證這功能一次搞懂!
Thumbnail
網站建置後,為了確保優秀的使用者體驗和網站的功能性,進行徹底的後續優化和測試是不可或缺的。以下是建議的重點測試項目: 響應式網頁設計(RWD)測試: 確保網站在各種設備(如桌面電腦、平板和手機)上均展示良好。這包括在不同的屏幕尺寸和解析度上測試,確保網站能夠自如適應不同的顯示需求。
Thumbnail
Heuristic 啟發式設計是用戶體驗設計的重要原則之一,涉及了許多與真實世界匹配、用戶控制、一致性和準則等方面,通過一些具體的例子解釋了這些原則的重要性。本文還提供了一些相關的視覺系統狀態和系統與真實世界匹配的例子,同時附帶了一些相關的教程和資料來源。
Thumbnail
「聯絡我們」頁面,對於許多人來說,可能只是一個填寫表格或放置聯絡資訊的地方。然而,在服務客戶的過程中,我經常被問到:網站真的需要這樣的頁面嗎?事實上,現今的聯絡方式多樣化,可以根據不同的需求和情境進行設計,讓我們來看看具體如何做。 服務性質的考量 考慮服務的性質是第一步。通常,服務性質會涵蓋多個
Thumbnail
確保沒有遺漏或錯誤 程式的完整資訊資料對於程式設計至關重要。這是因為只有透過完整的資訊,我們才能確保在程式設計中沒有任何遺漏或錯誤。最終,後台管理扮演著管理系統中所有動作和行為是否符合特定標準的重要角色。 採取不符合預期的行動 這種符合性的重要性在於,當我們設計程式時,希望使用者按照預期的方式
Thumbnail
資料的統合 在程式設計中,其他人通常關心是否注意到執行的細節。作為程式設計師,主要應該關心的是程式的表現,但往往忽略了很多細節,這些細節可以決定程式的好壞。程式的好壞很大程度上取決於資料的統合,也就是資料是否被正規化。 不同類型的資料在系統中呈現一致 正規化可能對一些人來說聽起來很抽象,有些人
Thumbnail
前言 現在的前端需求已經越來越高,要考慮HTML及CSS的切版美觀程度,以及React以及Flutter所提出的元件(Componet、widget)觀念,也就是將元件模組化,使元件可以更動態的被程式運行,而不用靜態的客製化每一個介面。開發一個好的元件可以提升整體的開發速度,讓任何使用元件的開發者
Thumbnail
前端開發者常會遇到需要網頁素材的情況,雖然在公司中都可能有可以配合的平面設計師或是UIUX設計師,但在這個多工高效的時代不免也需要前端開發者也可以處理簡單的設計,也可提升設計審美或與設計師溝通的能力。 然而前端開發者也算是擁有設計師的天賦,透過程式碼來完成平面設計,將網頁的每個介面都視為平面設計,
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
本文介紹瞭如何在後端系統開發時設計不同表單的簽核流程,包括請假表單和採購表單。以及如何動態生成簽核表單,並建立簽核節點。另外還介紹瞭如何利用繼承來簡化簽核流程的設定。
Thumbnail
這邊統整了過往喜特先生發布過的「資料驗證」系列文! 資料驗證是個「驗證資料是否符合某條件的機制」,我們通常會用它來避免別人輸入無效的值,減少錯誤的發生。你可以按照順序慢慢學習,把資料驗證這功能一次搞懂!
Thumbnail
網站建置後,為了確保優秀的使用者體驗和網站的功能性,進行徹底的後續優化和測試是不可或缺的。以下是建議的重點測試項目: 響應式網頁設計(RWD)測試: 確保網站在各種設備(如桌面電腦、平板和手機)上均展示良好。這包括在不同的屏幕尺寸和解析度上測試,確保網站能夠自如適應不同的顯示需求。
Thumbnail
Heuristic 啟發式設計是用戶體驗設計的重要原則之一,涉及了許多與真實世界匹配、用戶控制、一致性和準則等方面,通過一些具體的例子解釋了這些原則的重要性。本文還提供了一些相關的視覺系統狀態和系統與真實世界匹配的例子,同時附帶了一些相關的教程和資料來源。
Thumbnail
「聯絡我們」頁面,對於許多人來說,可能只是一個填寫表格或放置聯絡資訊的地方。然而,在服務客戶的過程中,我經常被問到:網站真的需要這樣的頁面嗎?事實上,現今的聯絡方式多樣化,可以根據不同的需求和情境進行設計,讓我們來看看具體如何做。 服務性質的考量 考慮服務的性質是第一步。通常,服務性質會涵蓋多個
Thumbnail
確保沒有遺漏或錯誤 程式的完整資訊資料對於程式設計至關重要。這是因為只有透過完整的資訊,我們才能確保在程式設計中沒有任何遺漏或錯誤。最終,後台管理扮演著管理系統中所有動作和行為是否符合特定標準的重要角色。 採取不符合預期的行動 這種符合性的重要性在於,當我們設計程式時,希望使用者按照預期的方式
Thumbnail
資料的統合 在程式設計中,其他人通常關心是否注意到執行的細節。作為程式設計師,主要應該關心的是程式的表現,但往往忽略了很多細節,這些細節可以決定程式的好壞。程式的好壞很大程度上取決於資料的統合,也就是資料是否被正規化。 不同類型的資料在系統中呈現一致 正規化可能對一些人來說聽起來很抽象,有些人
Thumbnail
前言 現在的前端需求已經越來越高,要考慮HTML及CSS的切版美觀程度,以及React以及Flutter所提出的元件(Componet、widget)觀念,也就是將元件模組化,使元件可以更動態的被程式運行,而不用靜態的客製化每一個介面。開發一個好的元件可以提升整體的開發速度,讓任何使用元件的開發者
Thumbnail
前端開發者常會遇到需要網頁素材的情況,雖然在公司中都可能有可以配合的平面設計師或是UIUX設計師,但在這個多工高效的時代不免也需要前端開發者也可以處理簡單的設計,也可提升設計審美或與設計師溝通的能力。 然而前端開發者也算是擁有設計師的天賦,透過程式碼來完成平面設計,將網頁的每個介面都視為平面設計,