最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React 使用Hooks簡化受控組件的狀態(tài)綁定

 更新時間:2019年03月18日 10:32:25   作者:stockholm  
這篇文章主要介紹了React 使用Hooks簡化受控組件的狀態(tài)綁定,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

開始之前

閱讀本文需要對以下幾項有一定了解

ECMAScript 6

文章中大量用到了 ES6 語法,比如解構(gòu)賦值和函數(shù)參數(shù)默認值、剩余參數(shù)、展開語法、箭頭函數(shù)等。

Hooks

React 在 16.8 版本中推出了 Hooks,它允許你在“函數(shù)組件”中使用“類組件”的一些特性。

React 本身提供了一些 Hooks,比如 useState、useReducer 等。通過在一個以“use”作為命名起始的函數(shù)中調(diào)用這些 Hooks,就得到了一個 custom Hook(自定義 Hook)。

Custom Hooks 允許我們把任何邏輯封裝到其中,以便于復用足夠小的組件邏輯。

Controlled Components

當我們把像 <input> <textarea> 和 <select> 這樣的 HTML 元素本身的狀態(tài)交給 React state 去管理,我們就得到了一個“受控組件”。

styled-components

一個與 React 契合良好的 CSS in JS 庫。它允許你使用 JS 編寫樣式,并編譯成純 CSS 文件。
下面代碼中所有的樣式都是使用它編寫的。如果對代碼中樣式的實現(xiàn)不是很感興趣的話, 這個可以跳過。

代碼實現(xiàn)

Input 組件

首先我們需要實現(xiàn)一個 Input 組件,我們將在該組件的基礎(chǔ)上進行輸入、校驗并提示。

Input.js

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const Wrap = styled.div({
 display: 'flex',
 flexDirection: 'column',

 label: { display: 'flex', alignItems: 'center' },

 input: {
  marginLeft: 8,
 },

 p: {
  color: 'red',
 },
});

function Input({ label, type, helperText, error, ...otherProps }) {
 return (
  <Wrap>
   <label>
    {label}:
    <input {...otherProps} type={type} />
   </label>
   {error && <p>{helperText}</p>}
  </Wrap>
 );
}

Input.propTypes = {
 label: PropTypes.string,
 type: PropTypes.string,
 helperText: PropTypes.string,
 error: PropTypes.bool,
};

export default Input;

該組件主要接收以下幾個 props:

  • label label 標簽的文本
  • type 賦值給原生 input 標簽的 type 屬性
  • error 數(shù)據(jù)類型為 Boolean,如果為 true 則表示當前表單域有錯誤,即驗證不通過
  • helperText 當前表單域驗證不通過時,顯示在表單域下方的提示文字
  • otherProps props 中除了上述四個以外的其他屬性,全部賦值給原生 input 標簽

Custom Hook

有了 UI 組件之后,就可以開始實現(xiàn)我們的自定義 Hook 了。

useInput.js

import { useState } from 'react';

export default function useInput({
 initValue = '',
 helperText = '',
 validator = () => true,
 validateTriggers = ['onChange'],
} = {}) {
 // 保存用戶輸入的值,使用 initValue 作為初始值
 const [value, setValue] = useState(initValue);
 // Boolean 類型,表示當前表單項的驗證狀態(tài)
 const [error, setError] = useState(false);

 function onChange(e) {
  const { value } = e.target;

  setValue(value);

  // 根據(jù) validateTriggers 的選項,決定是否要在 onChange 里進行校驗
  if (validateTriggers.includes('onChange')) {
   setError(!validator(value));
  }
 }

 /**
  * 根據(jù) validateTriggers 生成相應的事件處理器
  */
 function createEventHandlers() {
  const eventHandlers = {};

  validateTriggers.forEach(item => {
   // 生成相應的事件處理器,并在其中做輸入校驗。
   eventHandlers[item] = e => {
    const { value } = e.target;
    setError(!validator(value));
   };
  });

  return eventHandlers;
 }

 const eventHandlers = createEventHandlers();

 return {
  value,
  helperText,
  error,
  ...eventHandlers,
  onChange,
 };
}

useInput 接收一個 options 對象作為參數(shù),考慮到擴展性,使用一個配置對象作為參數(shù)比較好。

options 對象擁有以下幾個屬性:

  • initValue 輸入框的初始值
  • helperText 當表單驗證不通過時顯示的字符串
  • validator 用于進行表單驗證的函數(shù),接收 value 作為參數(shù),并返回一個 Boolean 值,表示表單驗證是否通過
  • validateTriggers 字符串數(shù)組,表明在哪個或哪幾個事件中調(diào)用 validator 進行輸入校驗。

在函數(shù)體中,我們調(diào)用兩次 useState 來初始化 value 和 error 的值,分別保存用戶輸入的值和當前表單域的校驗結(jié)果。
然后,聲明一個 onChange 方法用來綁定 input 元素的 change 事件,在該方法中,我們把用戶輸入的值賦值給 value,同時根據(jù) validateTriggers 的值,決定是否要在該方法中進行輸入校驗。該方法隨后會被返回出去,再作為 props 傳遞給相應的組件,完成受控組件的狀態(tài)綁定。

我們還需要聲明一個 createEventHandlers 方法,該方法通過遍歷 validateTriggers,生成相應的事件處理器,并在這些事件處理器中進行輸入校驗。

最后我們調(diào)用 createEventHandlers 方法,并把生成的 eventHandlers(事件處理器) 通過擴展運算符,插入到最終返回的對象中。

注意:這里我們需要把 onChange 放在最后,以免帶有狀態(tài)綁定的 onChange 方法被 eventHandlers 中的 onChange 覆蓋掉。

具體使用

現(xiàn)在讓我們來看看實際該如何使用:

import React from 'react';
import Input from './Input';
import useInput from './useInput';

// 用于驗證郵箱的正則表達式
const EMAIL_REG = /\S+@\S+\.\S+/;

export default function Form() {
 const email = useInput({
  initValue: '',
  helperText: '請輸入有效的郵箱!',
  validator: value => EMAIL_REG.test(value),
  validateTriggers: ['onBlur'],
 });

 const password = useInput({
  initValue: '',
  helperText: '密碼長度需要在 6-20 之間!',
  validator: value => value.length >= 6 && value.length <= 20,
  validateTriggers: ['onChange', 'onBlur'],
 });

 /**
  * 判斷是否禁用按鈕
  */
 function isButtonDisabled() {
  // 當郵箱或密碼未填寫時,或者郵箱或密碼輸入校驗未通過時,禁用按鈕
  return !email.value || !password.value || email.error || password.error;
 }

 /**
  * 處理表單提交
  */
 function handleButtonClick() {
  console.log('郵箱:', email.value);
  console.log('密碼:', password.value);
 }

 return (
  <div>
   <Input {...email} label="郵箱" type="email" />
   <Input {...password} label="密碼" type="password" />

   <button disabled={isButtonDisabled()} onClick={handleButtonClick}>
    登錄
   </button>
  </div>
 );
}

這里調(diào)用了兩次 useInput,初始化 email 和 password 表單域數(shù)據(jù)。

然后使用擴展運算符,把值全部賦給 Input 組件。只用了幾行代碼就完成了定義初始值和受控組件的綁定,是不是很方便?

當我們輸入郵箱的時候,并不會出現(xiàn)校驗提示,但是一旦從郵箱輸入框失去焦點以后,輸入的值就會被校驗,并根據(jù)校驗結(jié)果顯示相應的提示。而密碼輸入框,則會在輸入的過程中和失焦后都進行校驗。

總結(jié)

上面這個例子已經(jīng)可以處理基本的表單驗證,至于格式化用戶輸入的數(shù)據(jù)以及自定義收集表單域的值的時機等其他需求,我就不再演示了,大家可以自行設(shè)計。這也是 Hooks 的特殊之處,它讓我們可以更容易的復用邏輯代碼,可以根據(jù)需要自行編寫 custom Hooks。

文章中關(guān)于 useInput 的 API 設(shè)計只是眾多方案中的一種,只是為大家提供一些參考。你也可以把整個表單的狀態(tài)封裝到一個 useForm 方法中,統(tǒng)一管理所有表單域的狀態(tài)。

希望本文能為大家?guī)硪恍╆P(guān)于如何使用 Hooks 的靈感,即使從來沒有使用過 Hooks,也強烈建議大家嘗試一下。我已經(jīng)在項目中大量使用 Hooks 了,并且它也為我?guī)砹撕芎玫男Ч?/p>

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • React中使用antd組件的方法

    React中使用antd組件的方法

    antd?是基于?Ant?Design?設(shè)計體系的?React?UI?組件庫,主要用于研發(fā)企業(yè)級中后臺產(chǎn)品,這篇文章主要介紹了React中使用antd組件,需要的朋友可以參考下
    2022-09-09
  • React Native之prop-types進行屬性確認詳解

    React Native之prop-types進行屬性確認詳解

    本篇文章主要介紹了React Native之prop-types進行屬性確認詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • React useState超詳細講解用法

    React useState超詳細講解用法

    我正在處理的組件是表單的時間輸入。表單相對復雜,并且是動態(tài)生成的,根據(jù)嵌套在其他數(shù)據(jù)中的數(shù)據(jù)顯示不同的字段。我正在用useReducer管理表單的狀態(tài),到目前為止效果很好
    2022-11-11
  • 淺談React之狀態(tài)(State)

    淺談React之狀態(tài)(State)

    這篇文章主要介紹了淺談React之狀態(tài)(State),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • React+TypeScript+webpack4多入口配置詳解

    React+TypeScript+webpack4多入口配置詳解

    這篇文章主要介紹了React+TypeScript+webpack4多入口配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • react 項目中引入圖片的幾種方式

    react 項目中引入圖片的幾種方式

    本文主要介紹了react 項目中引入圖片,本文詳細的介紹了幾種方法,需要的朋友們下面隨著小編來一起學習學習吧
    2021-06-06
  • React memo減少重復渲染詳解

    React memo減少重復渲染詳解

    React.memo為高階組件。它與React.PureComponent 非常相似,但它適用于函數(shù)組件,但不適用于class組件。文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-10-10
  • 如何不使用eject修改create-react-app的配置

    如何不使用eject修改create-react-app的配置

    許多剛開始接觸create-react-app框架的同學,不免都會有個疑問:如何在不執(zhí)行eject操作的同時,修改create-react-app的配置。
    2021-04-04
  • react路由基礎(chǔ)解讀(Router、Link和Route)

    react路由基礎(chǔ)解讀(Router、Link和Route)

    這篇文章主要介紹了react路由基礎(chǔ)解讀(Router、Link和Route),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • React項目中使用zustand狀態(tài)管理的實現(xiàn)

    React項目中使用zustand狀態(tài)管理的實現(xiàn)

    zustand是一個用于狀態(tài)管理的小巧而強大的庫,本文主要介紹了React項目中使用zustand狀態(tài)管理的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2023-10-10

最新評論

精河县| 汾西县| 舟曲县| 青冈县| 通城县| 固镇县| 祁东县| 华阴市| 仁化县| 临桂县| 哈尔滨市| 京山县| 合川市| 公主岭市| 肥乡县| 宁阳县| 仙桃市| 宣武区| 安图县| 宁乡县| 油尖旺区| 拉萨市| 长治县| 监利县| 禄劝| 财经| 太谷县| 海伦市| 盖州市| 建昌县| 清水河县| 团风县| 宁远县| 泗水县| 安图县| 昌平区| 延川县| 修文县| 长泰县| 根河市| 蕉岭县|