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

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

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

初探 React 鉤子

React 訪問(wèn) DOM 節(jié)點(diǎn)

在 React 中,要想直接訪問(wèn) DOM 節(jié)點(diǎn)需要使用 React 的一項(xiàng)特性—— ref。

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

在 React 中,React 為我們提供了 useRef 鉤子 來(lái)創(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("請(qǐng)輸入正確的十六進(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("請(qǐng)輸入正確的rgb格式顏色值");
        }
      }
    }
  };
  return(
    <form onSubmit={toggleColor} style={{padding: '20px'}}>
      <label htmlFor="hexColor">十六進(jìn)制格式顏色:</label>
      <input name="hexColor" ref={hexColor} type="text" placeholder="請(qǐng)輸入十六進(jìn)制格式顏色"></input>
      <br/>
      <br/>
      <label htmlFor="rgbColor">rgb格式顏色:</label>
      <input name="rgbColor" ref={rgbColor} type="text" placeholder="請(qǐng)輸入rgb格式顏色"></input>
      <button>轉(zhuǎn)換</button>
    </form>
  )
}

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

受控組件

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

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

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("請(qǐng)輸入正確的十六進(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("請(qǐng)輸入正確的rgb格式顏色值");
        }
      }
    }
  };
  return(
    <form onSubmit={toggleColor} style={{padding: '20px'}}>
      <label htmlFor="hexColor">十六進(jìn)制格式顏色:</label>
      <input name="hexColor" type="text" value={hexColorStr} placeholder="請(qǐng)輸入十六進(jìn)制格式顏色" onChange={e => {setHexColorStr(e.target.value)}}></input>
      <br/>
      <br/>
      <label htmlFor="rgbColor">rgb格式顏色:</label>
      <input name="rgbColor" type="text" value={rgbColorStr} placeholder="請(qǐng)輸入rgb格式顏色" onChange={e => {setRgbColorStr(e.target.value)}}></input>
      <button>轉(zhuǎn)換</button>
    </form>
  )
}

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

如果感覺(jué)看代碼太麻煩,難以理解,我們來(lái)看看示意圖:

我們把代碼拿出來(lái)理一理就能得到一個(gè)很簡(jiǎn)單的邏輯圖,是不是一目了然。

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

自定義鉤子

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

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

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

// 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)
  ]
}

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

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("請(qǐng)輸入正確的十六進(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("請(qǐng)輸入正確的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="請(qǐng)輸入十六進(jìn)制格式顏色"></input>
      <button onClick={resetClick}>重置</button>
      <br/>
      <br/>
      <label htmlFor="rgbColor">rgb格式顏色:</label>
      <input {...rgbColorProps} name="rgbColor" type="text" placeholder="請(qǐng)輸入rgb格式顏色"></input>
      <button>轉(zhuǎn)換</button>
    </form>
  )
}

我們先來(lái)看看這兩行代碼的對(duì)比:

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

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

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

(custVal = initValue) => setValue(custVal)

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

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

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

總結(jié)

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

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

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

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

相關(guān)文章

  • React RenderProps模式超詳細(xì)講解

    React RenderProps模式超詳細(xì)講解

    render props是指一種在 React 組件之間使用一個(gè)值為函數(shù)的 prop 共享代碼的技術(shù)。簡(jiǎn)單來(lái)說(shuō),給一個(gè)組件傳入一個(gè)prop,這個(gè)props是一個(gè)函數(shù),函數(shù)的作用是用來(lái)告訴這個(gè)組件需要渲染什么內(nèi)容,那么這個(gè)prop就成為render prop
    2022-11-11
  • 使用React+ts實(shí)現(xiàn)無(wú)縫滾動(dòng)的走馬燈詳細(xì)過(guò)程

    使用React+ts實(shí)現(xiàn)無(wú)縫滾動(dòng)的走馬燈詳細(xì)過(guò)程

    這篇文章主要給大家介紹了關(guān)于使用React+ts實(shí)現(xiàn)無(wú)縫滾動(dòng)的走馬燈詳細(xì)過(guò)程,文中給出了詳細(xì)的代碼示例以及圖文教程,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-08-08
  • React Fiber結(jié)構(gòu)的創(chuàng)建步驟

    React Fiber結(jié)構(gòu)的創(chuàng)建步驟

    這篇文章主要介紹了React Fiber結(jié)構(gòu)的創(chuàng)建步驟,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-04-04
  • React Native之ListView實(shí)現(xiàn)九宮格效果的示例

    React Native之ListView實(shí)現(xiàn)九宮格效果的示例

    本篇文章主要介紹了React Native之ListView實(shí)現(xiàn)九宮格效果的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • React Native自定義組件與輸出方法詳解

    React Native自定義組件與輸出方法詳解

    這篇文章主要給大家介紹了關(guān)于React Native自定義組件與輸出方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • Redux Toolkit 實(shí)戰(zhàn)小結(jié)

    Redux Toolkit 實(shí)戰(zhàn)小結(jié)

    Redux曾是React狀態(tài)管理的標(biāo)準(zhǔn)解決方案,但傳統(tǒng) Redux 的樣板代碼過(guò)多、配置復(fù)雜、異步處理繁瑣,Redux Toolkit(RTK)官方推出,旨在解決這些痛點(diǎn),下面就來(lái)詳細(xì)的介紹一下如何使用
    2026-03-03
  • 在React中強(qiáng)制重新渲染的4 種方式案例代碼

    在React中強(qiáng)制重新渲染的4 種方式案例代碼

    這篇文章主要介紹了在React中強(qiáng)制重新渲染的4 種方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12
  • 基于CSS實(shí)現(xiàn)MaterialUI按鈕點(diǎn)擊動(dòng)畫(huà)并封裝成 React 組件

    基于CSS實(shí)現(xiàn)MaterialUI按鈕點(diǎn)擊動(dòng)畫(huà)并封裝成 React 組件

    筆者先后開(kāi)發(fā)過(guò)基于vue,react,angular等框架的項(xiàng)目,碧如vue生態(tài)的elementUI, ant-design-vue, iView等成熟的UI框架, react生態(tài)的ant-design, materialUI等,這些第三方UI框架極大的降低了我們開(kāi)發(fā)一個(gè)項(xiàng)目的成本和復(fù)雜度,使開(kāi)發(fā)者更專注于實(shí)現(xiàn)業(yè)務(wù)邏輯和服務(wù)化
    2021-11-11
  • 簡(jiǎn)易的redux?createStore手寫(xiě)實(shí)現(xiàn)示例

    簡(jiǎn)易的redux?createStore手寫(xiě)實(shí)現(xiàn)示例

    這篇文章主要介紹了簡(jiǎn)易的redux?createStore手寫(xiě)實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 工程級(jí)?React?注冊(cè)登錄全棧級(jí)流程分析

    工程級(jí)?React?注冊(cè)登錄全棧級(jí)流程分析

    這篇文章主要介紹了工程級(jí)?React?注冊(cè)登錄全棧級(jí)流程,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02

最新評(píng)論

北票市| 上虞市| 张家口市| 裕民县| 甘孜县| 翁牛特旗| 涪陵区| 滁州市| 出国| 迭部县| 乐山市| 西宁市| 革吉县| 乌鲁木齐县| 西丰县| 海阳市| 紫金县| 石狮市| 通化县| 潞城市| 曲阳县| 安龙县| 滕州市| 香港 | 衡阳市| 江都市| 敦化市| 阿城市| 西宁市| 衡东县| 秦安县| 舟山市| 从江县| 日土县| 平陆县| 宿州市| 科技| 玉树县| 海盐县| 青神县| 子长县|