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

詳解React中key的作用

 更新時(shí)間:2021年04月12日 09:26:31   作者:夏花未眠  
這篇文章主要介紹了React中key的作用,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下

要了解React中key的作用,可以從key的取值入手,key的取值可以分為三種,不定值、索引值、確定且唯一值

在下面的代碼中,key的取值是不定值(Math.random())

問題: 點(diǎn)擊按鈕的時(shí)候,span的顏色會(huì)變成紅色嗎?

import React, { useState } from 'react';

function App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const handleClick = () => {
    setInitMap([1,2,3,4])
    var spanEle = document.getElementsByTagName('span');
    Array.from(spanEle).map(it => it.style.color = 'red')
  }
  
  return (
    <div className="App" id="app">
      {
        initMap.map((it,index) => <div key={Math.random()}><span>color</span></div>)
      }
      <button onClick={() => handleClick()}></button>
    </div>
  );
}

export default App;

答案是:不會(huì)

這個(gè)問題涉及react渲染機(jī)制和diff算法

官網(wǎng)中對(duì)于diff有如下規(guī)則:

  • 當(dāng)元素類型變化時(shí),會(huì)銷毀重建
  • 當(dāng)元素類型不變時(shí),對(duì)比屬性
  • 當(dāng)組件元素類型不變時(shí),通過props遞歸判斷子節(jié)點(diǎn)
  • 遞歸對(duì)比子節(jié)點(diǎn),當(dāng)子節(jié)點(diǎn)是列表時(shí),通過key和props來判斷。若key一致,則進(jìn)行更新,若key不一致,就銷毀重建

分析上述問題:

當(dāng)點(diǎn)擊按鈕時(shí),setInitMap([1,2,3,4])會(huì)造成渲染,渲染時(shí)會(huì)生成新的虛擬dom,但此時(shí)獲取到的span元素是之前的元素(因?yàn)閟etInitMap是異步執(zhí)行的),所以新舊dom會(huì)做對(duì)比

在initMap.map((it,index) => <div key={Math.random()}><span>color</span></div>)這段代碼中

這里的div是列表,對(duì)比第四條diff規(guī)則,react會(huì)根據(jù)key來判斷是否更新真實(shí)dom。key= {Math.random()},新舊dom的值不一致,就會(huì)重新生成div。而我們是給更新之前的元素加了紅色的樣式,所以重新創(chuàng)建的元素上不會(huì)有這個(gè)樣式,效果如下

第二種情況:key的取值為索引值

上面我們分析的結(jié)果是,因?yàn)閗ey的變化,導(dǎo)致div元素在render的時(shí)候會(huì)重新生成。那如果key在render前后保持不變呢?例如,將key改為index

問題: 這段代碼在button點(diǎn)擊之后,span的顏色會(huì)變嗎?

return (
    <div className="App" id="app">
      <Spin spinning={spin}></Spin>
      {
        initMap.map((it,index) => <div key={index}><span>color</span></div>)
      }
      <button onClick={() => handleClick()}></button>
    </div>
  );

答案:會(huì)

分析: 因?yàn)樵趓ender前后,index不變,所以div不會(huì)重新生成,接著對(duì)比span元素,span元素在render前后,屬性變化,因此react只會(huì)為span元素應(yīng)用新的屬性,但是他們指向的還是之前的元素

第三種情況:key的取值確定且唯一:

在這個(gè)例子中,通過將key設(shè)置成index,span的顏色有了變化,但是在使用key時(shí),React官網(wǎng)不推薦使用index

改造一下上面的代碼

  const [initMap, setInitMap] = useState([1,2,3,4]);
  const handleClick = () => {
    setInitMap([3,2,1,4])
  }
  return (
    <div className="App" id="app">
      {
        initMap.map((it,index) => <div key={index}><input type="radio" />{it}</div>)
      }
      <button onClick={() => handleClick()}>點(diǎn)擊</button>
    </div>
  );
}

在初始化的時(shí)候選中值為3的按鈕

點(diǎn)擊按鈕

我們預(yù)期的效果是,選中的依舊是值為3的按鈕,但此時(shí)變成了值為1的按鈕

分析:

  1. setState之后會(huì)導(dǎo)致render
  2. div的index不變,所以div不會(huì)重新生成,input不受state和props控制,因此元素的狀態(tài)不變
  3. 所以變化的只有受state影響的it

如果想要達(dá)到預(yù)期效果,我們要設(shè)置唯一且確定的key

測(cè)試一:

{
   initMap.map((it) => <div key={it}><input type="radio" />{it}</div>)
}

初始化的時(shí)候選中第三個(gè)按鈕

點(diǎn)擊按鈕

這才是符合預(yù)期的效果

思考一下,將key設(shè)置為Math.random(),會(huì)有什么效果?按鈕的狀態(tài)會(huì)保留嗎?

點(diǎn)擊前:

點(diǎn)擊后:

radio的狀態(tài)不會(huì)被保留

通過上面的例子,我們大概可以理解React中key的作用了,下面的內(nèi)容是對(duì)React知識(shí)點(diǎn)的一些擴(kuò)展

擴(kuò)展內(nèi)容: 文章開始的代碼還涉及React兩個(gè)其他知識(shí)點(diǎn),一個(gè)是提到過的React渲染條件,一個(gè)是對(duì)真實(shí)dom的操作;

擴(kuò)展一: React渲染條件

import './App.css';
import React, { useState } from 'react';

function App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const [spin, setSpin] = useState(false);
  const handleClick = () => {
    setSpin(true); //變化部分
    var spanEle = document.getElementsByTagName('span');
    Array.from(spanEle).map(it => it.style.color = 'red')
    setSpin(false); //變化部分
  }
  
  return (
    <div className="App" id="app">
      <Spin spinning={spin}></Spin>
      {
        initMap.map((it,index) => <div key={Math.random()}><span>{it}</span></div>)
      }
      <button onClick={() => handleClick()}></button>
    </div>
  );
}

export default App;

測(cè)試結(jié)果如下 點(diǎn)擊前:

點(diǎn)擊后:

在這段代碼中,div的key仍然使用的是Math.random(),但initMap的state并沒有改變,所以沒有重新渲染,此時(shí)div不會(huì)銷毀重建

擴(kuò)展二:是否可以對(duì)真實(shí)dom操作

在React中,虛擬dom的出現(xiàn)是為了減少對(duì)真實(shí)dom的操作,因?yàn)檎鎸?shí)的dom元素是一個(gè)較復(fù)雜的對(duì)象,操作的話計(jì)算量比較大。我們上面的代碼中,都是直接操作dom節(jié)點(diǎn),更改樣式,這樣并不可取。由于React是根據(jù)state和props的變化來渲染頁(yè)面,因此通過state來控制頁(yè)面渲染比較好

修改后的代碼如下:

function App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const [spin, setSpin] = useState(false);
  const [showColor, setShowColor] = useState(false);
  const handleClick = () => {
    setInitMap([3,2,1,4]);
    setShowColor(true);
  }
  
  return (
    <div className="App" id="app">
      <Spin spinning={spin}>
      {
        initMap.map((it,index) => <div key={Math.random()}><span className={showColor && 'span-color'}>color</span></div>)
      }
      </Spin>
      <button onClick={() => handleClick()}>點(diǎn)擊</button>
    </div>
  );
}

此時(shí)span是受控組件,可以通過showColor的狀態(tài)控制元素的渲染

點(diǎn)擊前:

點(diǎn)擊后:

使用state控制渲染后,代碼量會(huì)變少,同時(shí)結(jié)果符合預(yù)期

總結(jié)

  1. 在使用key時(shí),要保證key的唯一和確定性,如果key的值為Math.random(),可能造成組件重新構(gòu)建,使之前對(duì)元素的操作失效
  2. 在渲染頁(yè)面時(shí),盡量不要操作真實(shí)的dom,使用state來更新頁(yè)面

以上就是詳解React中key的作用的詳細(xì)內(nèi)容,更多關(guān)于React key的作用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React18新特性startTransition詳解

    React18新特性startTransition詳解

    React18的新特性startTransition主要是為了優(yōu)化用戶體驗(yàn),通過標(biāo)記低優(yōu)先級(jí)的更新任務(wù),如頁(yè)面重渲染,使它們不會(huì)阻塞高優(yōu)先級(jí)的緊急任務(wù)如用戶輸入響應(yīng),本文介紹React18新特性startTransition,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • ReactJS實(shí)現(xiàn)表單的單選多選和反選的示例

    ReactJS實(shí)現(xiàn)表單的單選多選和反選的示例

    本篇文章主要介紹了ReactJS實(shí)現(xiàn)表單的單選多選和反選的示例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-10-10
  • 手動(dòng)用webpack搭建第一個(gè)ReactApp的示例

    手動(dòng)用webpack搭建第一個(gè)ReactApp的示例

    本篇文章主要介紹了手動(dòng)用webpack搭第一個(gè) ReactApp的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • React 的調(diào)和算法Diffing 算法策略詳解

    React 的調(diào)和算法Diffing 算法策略詳解

    React的調(diào)和算法,主要發(fā)生在render階段,調(diào)和算法并不是一個(gè)特定的算法函數(shù),而是指在調(diào)和過程中,為提高構(gòu)建workInProcess樹的性能,以及Dom樹更新的性能,而采用的一種策略,又稱diffing算法
    2021-12-12
  • React videojs 實(shí)現(xiàn)自定義組件(視頻畫質(zhì)/清晰度切換) 的操作代碼

    React videojs 實(shí)現(xiàn)自定義組件(視頻畫質(zhì)/清晰度切換) 的操作代碼

    最近使用videojs作為視頻處理第三方庫(kù),用來對(duì)接m3u8視頻類型,這里總結(jié)一下自定義組件遇到的問題及實(shí)現(xiàn),感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • react+antd動(dòng)態(tài)增刪表單方式

    react+antd動(dòng)態(tài)增刪表單方式

    這篇文章主要介紹了react+antd動(dòng)態(tài)增刪表單方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • VSCode 配置React Native開發(fā)環(huán)境的方法

    VSCode 配置React Native開發(fā)環(huán)境的方法

    本篇文章主要介紹了VSCode 配置React Native開發(fā)環(huán)境的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • React實(shí)現(xiàn)控制減少useContext導(dǎo)致非必要的渲染詳解

    React實(shí)現(xiàn)控制減少useContext導(dǎo)致非必要的渲染詳解

    這篇文章主要介紹了React如何有效減少使用useContext導(dǎo)致的不必要渲染,使用useContext在改變一個(gè)數(shù)據(jù)時(shí),是通過自己逐級(jí)查找對(duì)比改變的數(shù)據(jù)然后渲染,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-11-11
  • vite?+?react?+typescript?環(huán)境搭建小白入門教程

    vite?+?react?+typescript?環(huán)境搭建小白入門教程

    這篇文章主要介紹了vite?+?react?+typescript?環(huán)境搭建小白入門教程,本文通過示例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • 基于React.js實(shí)現(xiàn)兔兔牌九宮格翻牌抽獎(jiǎng)組件

    基于React.js實(shí)現(xiàn)兔兔牌九宮格翻牌抽獎(jiǎng)組件

    這篇文章主要為大家詳細(xì)介紹了如何基于React.js實(shí)現(xiàn)兔兔牌九宮格翻牌抽獎(jiǎng)組件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-01-01

最新評(píng)論