欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于React的狀態(tài)管理實現(xiàn)一個簡單的顏色轉(zhuǎn)換器

 更新時間:2023年08月27日 10:43:33   作者:炭烤小橙微辣  
這篇文章主要介紹了用React的狀態(tài)管理,簡簡單單實現(xiàn)一個顏色轉(zhuǎn)換器,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下

初探 React 鉤子

React 訪問 DOM 節(jié)點

在 React 中,要想直接訪問 DOM 節(jié)點需要使用 React 的一項特性—— ref。

ref:是一個對象,存儲一個組件整個生命周期內(nèi)的值。

在 React 中,React 為我們提供了 useRef 鉤子 來創(chuàng)建 ref。

import { useRef } from "react";
export default function ChangeColorForm() {
  const hexColor = useRef();
  const rgbColor = useRef();
  const getFullHexColorStr = str => {
    if (isNaN(parseInt(str, 16))) {
      alert("請輸入正確的十六進(jìn)制顏色值");
      return '';
    }
    if (str.length === 3) {
      return str.split('').map(item => item + item).join('');
    } else {
      const lastChar = str.charAt(str.length - 1);
      const strArr = [...Array(5)];
      return str + strArr.map(s => lastChar).join("");
    }
  }
  const toggleColor = e => {
    e.preventDefault();
    const hexColorStr = hexColor.current.value;
    const rgbColorStr = rgbColor.current.value;
    if (hexColorStr) {
      const hexColor = getFullHexColorStr(hexColorStr).toUpperCase();
        if (!hexColor) {
          return;
        }
        const strArr = [...Array(6)];
        const rgbColorArr = strArr.reduce((pre, cur, index) => {
          if (index % 2 === 1) {
            pre = [...pre, parseInt(hexColor.substring(index - 1, index + 1), 16)];
          }
          return pre;
        },[]);
        rgbColor.current.value = rgbColorArr.join(',');
    } else {
      if (rgbColorStr) {
        const rgbColorArr = rgbColorStr.split(',');
        const isRightLength = rgbColorArr.length === 3;
        const isRightRGB = rgbColorArr.every(colorNum => !isNaN(Number(colorNum) && Number(colorNum) >= 0 && Number(colorNum) <= 255))
        if (isRightLength && isRightRGB) {
          const hexColorArr = rgbColorArr.map(colorNum => Number(colorNum).toString(16));
          hexColor.current.value = hexColorArr.join('').toUpperCase();
        } else {
          alert("請輸入正確的rgb格式顏色值");
        }
      }
    }
  };
  return(
    <form onSubmit={toggleColor} style={{padding: '20px'}}>
      <label htmlFor="hexColor">十六進(jìn)制格式顏色:</label>
      <input name="hexColor" ref={hexColor} type="text" placeholder="請輸入十六進(jìn)制格式顏色"></input>
      <br/>
      <br/>
      <label htmlFor="rgbColor">rgb格式顏色:</label>
      <input name="rgbColor" ref={rgbColor} type="text" placeholder="請輸入rgb格式顏色"></input>
      <button>轉(zhuǎn)換</button>
    </form>
  )
}

這里我們手動寫了一個關(guān)于十六進(jìn)制顏色值與RGB顏色值互轉(zhuǎn)的簡易工具,代碼里邊我們來看一看 useRef 鉤子的用法,我們用 useRef 鉤子創(chuàng)建了兩個 ref,分別在 JSX 中 input 標(biāo)簽中添加 ref 屬性,那么我們就不再需要通過選擇器來獲取 DOM 元素了,直接在 ref 對象中去取 DOM 元素就可以了,從代碼中我們可以看到,這個 DOM 元素存儲在 ref 對象中的 current 屬性中。

受控組件

在 React 中,受控組件就是以組件內(nèi)部狀態(tài)來管理組件內(nèi)部值得變化的組件。而上一節(jié)我們提到了組件的狀態(tài)有 React 提供的 useState 鉤子來進(jìn)行控制,我們可以理解成受控組件就是由狀態(tài)來控制屬性值變化得組件,由父組件屬性傳遞和事件來驅(qū)動狀態(tài)的變化,使數(shù)據(jù)產(chǎn)生流動的效果。當(dāng)然,數(shù)據(jù)流動的效果也注定使組件不斷的重新渲染,這一點,我們也必須要了解。

既然這樣,我們來讓這個顏色碼值轉(zhuǎn)換表單組件改成一個受控組件:

import { useState } from "react";
export default function ChangeColorForm() {
  const [hexColorStr, setHexColorStr] = useState('FFFFFF');
  const [rgbColorStr, setRgbColorStr] = useState('');
  const getFullHexColorStr = str => {
    if (isNaN(parseInt(str, 16))) {
      alert("請輸入正確的十六進(jìn)制顏色值");
      return '';
    }
    if (str.length === 3) {
      return str.split('').map(item => item + item).join('');
    } else {
      const lastChar = str.charAt(str.length - 1);
      const strArr = [...Array(5)];
      return str + strArr.map(() => lastChar).join("");
    }
  }
  const toggleColor = e => {
    e.preventDefault();
    if (hexColorStr) {
      const hexColor = getFullHexColorStr(hexColorStr).toUpperCase();
        if (!hexColor) {
          return;
        }
        const strArr = [...Array(6)];
        const rgbColorArr = strArr.reduce((pre, cur, index) => {
          if (index % 2 === 1) {
            pre = [...pre, parseInt(hexColor.substring(index - 1, index + 1), 16)];
          }
          return pre;
        },[]);
        setRgbColorStr(rgbColorArr.join(','));
    } else {
      if (rgbColorStr) {
        const rgbColorArr = rgbColorStr.split(',');
        const isRightLength = rgbColorArr.length === 3;
        const isRightRGB = rgbColorArr.every(colorNum => !isNaN(Number(colorNum) && Number(colorNum) >= 0 && Number(colorNum) <= 255))
        if (isRightLength && isRightRGB) {
          const hexColorArr = rgbColorArr.map(colorNum => Number(colorNum).toString(16));
          setHexColorStr(hexColorArr.join('').toUpperCase());
        } else {
          alert("請輸入正確的rgb格式顏色值");
        }
      }
    }
  };
  return(
    <form onSubmit={toggleColor} style={{padding: '20px'}}>
      <label htmlFor="hexColor">十六進(jìn)制格式顏色:</label>
      <input name="hexColor" type="text" value={hexColorStr} placeholder="請輸入十六進(jìn)制格式顏色" onChange={e => {setHexColorStr(e.target.value)}}></input>
      <br/>
      <br/>
      <label htmlFor="rgbColor">rgb格式顏色:</label>
      <input name="rgbColor" type="text" value={rgbColorStr} placeholder="請輸入rgb格式顏色" onChange={e => {setRgbColorStr(e.target.value)}}></input>
      <button>轉(zhuǎn)換</button>
    </form>
  )
}

在組件中,通過 React 的狀態(tài)來保存兩個 input 元素的值,只要觸發(fā)了 onChange 事件,通過參數(shù) e(event).target 來獲取 DOM,獲取元素值再通過狀態(tài)設(shè)置函數(shù)來將狀態(tài)值更新,使得 DOM 重新渲染,將值又賦值進(jìn)輸入框,形成一個閉合回路。

如果感覺看代碼太麻煩,難以理解,我們來看看示意圖:

我們把代碼拿出來理一理就能得到一個很簡單的邏輯圖,是不是一目了然。

上面我們利用狀態(tài)創(chuàng)建的受控組件中,input 元素只有兩個,但是在實際的開發(fā)中,對應(yīng)的 input 元素可能有十多二十個甚至更多,按照這樣的方法,那是不是得這樣重復(fù)操作很多次,之前我們提到過,遇到重復(fù)的,結(jié)構(gòu)相似的代碼,考慮一下是否可以抽象出來封裝一下呢?下面我們來介紹一下自定義的鉤子。

自定義鉤子

從上面的代碼我們可以看到,定義狀態(tài),input 元素中賦值 value,onChange 方法,他們的結(jié)構(gòu)是不是基本都是一樣的呢?我們先來看看定義狀態(tài)是不是可以抽象為:

// initValue 初始值參數(shù)
const [value, setValue] = useState(initValue);

對于 input 元素中的屬性賦值,我們還能想起屬性較多的時候,整體屬性的傳遞方法嗎?估計能想起來{...props};那我們能否把 value,跟 onChange 封裝在一個對象里邊呢?然后用一個函數(shù)返回回來。我們新建一個 hooks.js文件,來看看怎么封裝。

// hooks.js
import { useState } from "react";
export const useInput = initValue => {
  const [value, setValue] = useState(initValue);
  return [
    {value, onChange: (e) => setValue(e.target.value)},
    (custVal = initValue) => setValue(custVal)
  ]
}

一眼看完,可能還沒明白為啥要這樣封裝,先暫時不說,我們還是再來把顏色轉(zhuǎn)換器繼續(xù)優(yōu)化一下,再來看看為啥這么封裝?

import { useInput } from "./hooks";
export default function ChangeColorForm() {
  const [hexColorProps, setHexColorStr] = useInput('FFFFFF');
  const [rgbColorProps, setRgbColorStr] = useInput('');
  const getFullHexColorStr = str => {
    if (isNaN(parseInt(str, 16))) {
      alert("請輸入正確的十六進(jìn)制顏色值");
      return '';
    }
    if (str.length === 3) {
      return str.split('').map(item => item + item).join('');
    } else {
      const lastChar = str.charAt(str.length - 1);
      const strArr = [...Array(5)];
      return str + strArr.map(() => lastChar).join("");
    }
  }
  const toggleColor = e => {
    e.preventDefault();
    if (hexColorProps.value) {
      const hexColor = getFullHexColorStr(hexColorProps.value).toUpperCase();
        if (!hexColor) {
          return;
        }
        const strArr = [...Array(6)];
        const rgbColorArr = strArr.reduce((pre, cur, index) => {
          if (index % 2 === 1) {
            pre = [...pre, parseInt(hexColor.substring(index - 1, index + 1), 16)];
          }
          return pre;
        },[]);
        setRgbColorStr(rgbColorArr.join(','));
    } else {
      if (rgbColorProps.value) {
        const rgbColorArr = rgbColorProps.value.split(',');
        const isRightLength = rgbColorArr.length === 3;
        const isRightRGB = rgbColorArr.every(colorNum => !isNaN(Number(colorNum) && Number(colorNum) >= 0 && Number(colorNum) <= 255))
        if (isRightLength && isRightRGB) {
          const hexColorArr = rgbColorArr.map(colorNum => Number(colorNum).toString(16));
          setHexColorStr(hexColorArr.join('').toUpperCase());
        } else {
          alert("請輸入正確的rgb格式顏色值");
        }
      }
    }
  };
  const resetClick = e => {
    e.preventDefault();
    setHexColorStr();
  }
  return(
    <form onSubmit={toggleColor} style={{padding: '20px'}}>
      <label htmlFor="hexColor">十六進(jìn)制格式顏色:</label>
      <input {...hexColorProps} name="hexColor" type="text" placeholder="請輸入十六進(jìn)制格式顏色"></input>
      <button onClick={resetClick}>重置</button>
      <br/>
      <br/>
      <label htmlFor="rgbColor">rgb格式顏色:</label>
      <input {...rgbColorProps} name="rgbColor" type="text" placeholder="請輸入rgb格式顏色"></input>
      <button>轉(zhuǎn)換</button>
    </form>
  )
}

我們先來看看這兩行代碼的對比:

// useState React 鉤子
const [hexColorStr, setHexColorStr] = useState('FFFFFF');
// useInput 自定義鉤子
const [hexColorProps, setHexColorStr] = useInput('FFFFFF');

useState 鉤子我們已經(jīng)用得比較熟悉,熟悉了它的用法與結(jié)構(gòu),當(dāng)我們需要封裝自定義鉤子的時候,當(dāng)函數(shù)能返回跟原始鉤子保持一致的結(jié)構(gòu)時,當(dāng)在使用的時候,是不是就會更加的輕松呢?值得注意的是,這里的 hexColorProps 是包含了 value, onChange 的多屬性的屬性值,在使用的時候我們是需要注意跟 useState 定義的屬性值得區(qū)別。

在這次的代碼中,我故意添加了一個重置按鈕,估計用意你們已經(jīng)猜到,很直白,就是為了講解一下 hooks.js 中的這個方法:

(custVal = initValue) => setValue(custVal)

隨著 ESNext 的不斷更新,前端的代碼也是越來越簡單,但是只要我們慢慢分析,還是很好理解的,我們來看一下對應(yīng) ES5 的代碼:

function (custVal) {
  custVal = custVal ? custVal : initValue;
  return setValue(custVal)
}

在實際的開發(fā)中,會遇到比較多的表單的聯(lián)動與重置,不難看出這個方法,就是為給 input 元素提供外部事件(非input 元素的 onChange 事件)來更改或重置 input元素的 value 屬性值。

總結(jié)

  • ref:是一個對象,存儲一個組件整個生命周期內(nèi)的值,DOM 元素存儲在 ref 對象中的 current 屬性中;

  • 受控組件:是由狀態(tài)來控制屬性值變化得組件,由父組件屬性傳遞和事件來驅(qū)動狀態(tài)的變化,使數(shù)據(jù)產(chǎn)生流動的效果;

  • 自定義鉤子:根據(jù)已知組件,方法的封裝,在封裝時盡可能保持與原組件,方法的參數(shù),返回值結(jié)構(gòu)保持一致。

以上就是基于React的狀態(tài)管理實現(xiàn)一個簡單的顏色轉(zhuǎn)換器的詳細(xì)內(nèi)容,更多關(guān)于React實現(xiàn)顏色轉(zhuǎn)換器的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React中常見的動畫實現(xiàn)的幾種方式

    React中常見的動畫實現(xiàn)的幾種方式

    本篇文章主要介紹了React中常見的動畫實現(xiàn)的幾種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • React Render Props共享代碼技術(shù)

    React Render Props共享代碼技術(shù)

    render props是指一種在 React 組件之間使用一個值為函數(shù)的 prop 共享代碼的技術(shù)。簡單來說,給一個組件傳入一個prop,這個props是一個函數(shù),函數(shù)的作用是用來告訴這個組件需要渲染什么內(nèi)容,那么這個prop就成為render prop
    2023-01-01
  • React?Streaming?SSR原理示例深入解析

    React?Streaming?SSR原理示例深入解析

    這篇文章主要為大家介紹了React?Streaming?SSR原理示例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • React組件通信淺析

    React組件通信淺析

    這篇文章主要介紹了React組件通信,在開發(fā)中組件通信是React中的一個重要的知識點,本文通過實例代碼給大家講解react中常用的父子、跨組件通信的方法,需要的朋友可以參考下
    2022-12-12
  • React+TypeScript項目中使用CodeMirror的步驟

    React+TypeScript項目中使用CodeMirror的步驟

    CodeMirror被廣泛應(yīng)用于許多Web應(yīng)用程序和開發(fā)工具,之前做需求用到過codeMirror這個工具,覺得還不錯,功能很強(qiáng)大,所以記錄一下改工具的基礎(chǔ)用法,對React+TypeScript項目中使用CodeMirror的步驟感興趣的朋友跟隨小編一起看看吧
    2023-07-07
  • 簡單的React SSR服務(wù)器渲染實現(xiàn)

    簡單的React SSR服務(wù)器渲染實現(xiàn)

    這篇文章主要介紹了簡單的React SSR服務(wù)器渲染實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • hooks寫React組件的5個注意細(xì)節(jié)詳解

    hooks寫React組件的5個注意細(xì)節(jié)詳解

    這篇文章主要為大家介紹了hooks寫React組件的5個需要注意的細(xì)節(jié)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 使用react在修改state中的數(shù)組和對象數(shù)據(jù)的時候(setState)

    使用react在修改state中的數(shù)組和對象數(shù)據(jù)的時候(setState)

    這篇文章主要介紹了使用react在修改state中的數(shù)組和對象數(shù)據(jù)的時候(setState),具有很好的參考價值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 解決react中l(wèi)abel標(biāo)簽for報錯問題

    解決react中l(wèi)abel標(biāo)簽for報錯問題

    這篇文章主要介紹了react中l(wèi)abel標(biāo)簽for報錯問題,解決辦法就是react中l(wèi)abel標(biāo)簽沒有for屬性,用htmlFor代替for屬性,感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • react-router-dom6(對比?router5)快速入門指南

    react-router-dom6(對比?router5)快速入門指南

    這篇文章主要介紹了快速上手react-router-dom6(對比?router5),通過本文學(xué)習(xí)最新的react-router-dom?v6版本的路由知識,并且會與v5老版本進(jìn)行一些對比,需要的朋友可以參考下
    2022-08-08

最新評論