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

React函數(shù)組件與類(lèi)的區(qū)別有哪些

 更新時(shí)間:2022年10月22日 10:21:44   作者:YinJie…  
函數(shù)式組件的基本意義就是,組件實(shí)際上是一個(gè)函數(shù),不是類(lèi),下面這篇文章主要給大家介紹了關(guān)于React中函數(shù)組件與類(lèi)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

首先我們要知道的是,項(xiàng)目性能能主要取決于代碼的作用,而不是選擇函數(shù)式還是類(lèi)組件。盡管優(yōu)化策略各有略微不同,但它們之間的性能差異可以忽略不計(jì)。

一、函數(shù)式組件捕獲了渲染所用的值

首先我們來(lái)看下面這個(gè)組件:

function App(props) {
  const showMessage = () => {
    alert('Hello' + props.user);
  };
  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };
  return (
    <button onClick={handleClick}>Say</button>
  );
}

它渲染了一個(gè)利用來(lái)模擬網(wǎng)絡(luò)請(qǐng)求,然后顯示一個(gè)確認(rèn)警告的按鈕。例如,如果是傳遞進(jìn)來(lái)的 props.user 是 jie,那么三秒后就會(huì)彈出 Hello jie。

那么我們用類(lèi)應(yīng)該怎么寫(xiě)這個(gè)組件呢?一個(gè)簡(jiǎn)單的重構(gòu)可能就象這樣:

class App extends React.Component {
  showMessage = () => {
    alert('Hello' + this.props.user);
  };
  handleClick = () => {
    setTimeout(this.showMessage, 3000);
  };
  render() {
    return <button onClick={this.handleClick}>Say</button>;
  }
}

我們通常做代碼重構(gòu)的時(shí)候都認(rèn)為他們兩個(gè)是等效的,但是事實(shí)真的如此嗎,我們很少注意到它們之間的含義。

下面我們新建一個(gè) react 項(xiàng)目,在 src下新建兩個(gè)組件,一個(gè) classComponent 組件,一個(gè)是 functionComponent 組件。代碼就是上面我們寫(xiě)的這兩個(gè)組件,只不過(guò)內(nèi)容稍有區(qū)別:

classComponent:

import React from 'react';
class ProfilePage extends React.Component {
  showMessage = () => {
    alert('你選擇了 ' + this.props.user);
  };
  handleClick = () => {
    setTimeout(this.showMessage, 3000);
  };
  render() {
    return <button onClick={this.handleClick}>選擇</button>;
  }
}
export default ProfilePage;

functionComponent:

import React from 'react';
function ProfilePage(props) {
  const showMessage = () => {
    alert('你選擇了 ' + props.user);
  };
  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };
  return (
    <button onClick={handleClick}>選擇</button>
  );
}
export default ProfilePage;

在 app.js 中我們將這兩個(gè)組件引入:

import React from "react";
import ReactDOM from "react-dom";
import ProfilePageFunction from './functionComponent';
import ProfilePageClass from './classComponent';
export default class App extends React.Component {
  state = {
    user: '小杰',
  };
  render() {
    return (
      <>
        <label>
          <b>選擇你想要拜訪的朋友</b>
          <select
            value={this.state.user}
            onChange={e => this.setState({ user: e.target.value })}
          >
            <option value="小杰">小杰</option>
            <option value="小尚">小尚</option>
            <option value="小寧">小寧</option>
          </select>
        </label>
        <h1>歡迎來(lái)到 {this.state.user}的 家!</h1>
        <p>
          <ProfilePageFunction user={this.state.user} />
          <b> (這是來(lái)自函數(shù)式組件的)</b>
        </p>
        <p>
          <ProfilePageClass user={this.state.user} />
          <b> (這是來(lái)自類(lèi)組件的)</b>
        </p>
      </>
    )
  }
}

運(yùn)行項(xiàng)目,科研看到這樣的界面:

當(dāng)我們單擊上面的按鈕時(shí),執(zhí)行的就是函數(shù)式組件,點(diǎn)擊下面的按鈕時(shí),執(zhí)行的就是類(lèi)。如果按照我們以往的思路,他們二者都會(huì)有相同的結(jié)果,但事實(shí)真的如此嗎?

我們按照下面的順序執(zhí)行:

1. 點(diǎn)擊函數(shù)式組件按鈕

2. 在點(diǎn)擊后立刻切換想要拜訪的朋友

函數(shù)式組件的執(zhí)行結(jié)果如下:

頁(yè)面彈出的還是我們當(dāng)時(shí)選擇的值

同樣的操作我們?cè)僭囈幌骂?lèi)組件:

現(xiàn)在頁(yè)面彈出的就是我們實(shí)時(shí)更改的值了。

在這個(gè)例子中,第一個(gè)行為是正確的。因?yàn)樽铋_(kāi)始我選擇要拜訪小杰點(diǎn)擊了確定發(fā)出了命令,然后我再切換到小尚,但是我并沒(méi)有點(diǎn)擊確定,我的組件不應(yīng)該混淆我要拜訪的人。在這里,類(lèi)組件的實(shí)現(xiàn)很明顯是錯(cuò)誤的。

所以為什么我們的例子中類(lèi)組件會(huì)有這樣的表現(xiàn)?

讓我們來(lái)仔細(xì)看看我們類(lèi)組件中的方法:showMessage

showMessage = () => {
    alert('你選擇了 ' + this.props.user);
  };

這個(gè)類(lèi)方法從中讀取數(shù)據(jù)。在 React 中 Props 是不可變的,所以他們永遠(yuǎn)不會(huì)改變。然而,this是,而且永遠(yuǎn)是,可變的。

事實(shí)上,這就是類(lèi)組件存在的意義。React本身會(huì)隨著時(shí)間的推移而改變,以便你可以在渲染方法以及生命周期方法中得到最新的實(shí)例。所以如果在請(qǐng)求已經(jīng)發(fā)出的情況下我們的組件進(jìn)行了重新渲染,將會(huì)改變。

我們的組件屬于一個(gè)擁有特定 props 和 state 的特定渲染。

然而,調(diào)用一個(gè)回調(diào)函數(shù)讀取 的 timeout 會(huì)打斷這種關(guān)聯(lián)。我們的回調(diào)并沒(méi)有與任何一個(gè)特定的渲染綁定在一起,所以它失去了正確的 props。

二、閉包讓類(lèi)組件成為擁有特定props和state的渲染

我們想要以某種方式“修復(fù)”擁有正確 props 的渲染與讀取這些 props 的回調(diào)之間的聯(lián)系。它們?cè)陬?lèi)的某個(gè)地方被弄丟了。

一種方法是在調(diào)用事件之前讀取,然后將他們顯式地傳遞到timeout回調(diào)函數(shù)中去:

import React from 'react';
class ProfilePage extends React.Component {
  showMessage = (user) => {
    alert('你選擇了 ' + user);
  };
  handleClick = () => {
    const {user} = this.props;
    setTimeout(() => this.showMessage(user), 3000);
  };
  render() {
    return <button onClick={this.handleClick}>確定</button>;
  }
}
export default ProfilePage;

這種方法會(huì)起作用。然而,這種方法使得代碼明顯變得更加冗長(zhǎng),并且隨著時(shí)間推移容易出錯(cuò)。如果我們需要的不止是一個(gè)props怎么辦?如果我們還需要訪問(wèn)state怎么辦?

然而,如果我們能利用JavaScript閉包的話(huà)問(wèn)題將迎刃而解。

通常來(lái)說(shuō)我們會(huì)避免使用閉包,但是在React中,props和state是不可變的,這就消除了閉包的一個(gè)主要缺陷。

這就意味著如果你在一次特定的渲染中捕獲那一次渲染所用的props或者state,你會(huì)發(fā)現(xiàn)他們總是會(huì)保持一致,就如同你的預(yù)期那樣。

class ProfilePage extends React.Component {
  render() {
    const props = this.props;
    const showMessage = () => {
      alert('你選擇了 ' + props.user);
    };
    const handleClick = () => {
      setTimeout(showMessage, 3000);
    };
    return <button onClick={handleClick}>確定</button>;
  }
}

你在渲染的時(shí)候就已經(jīng)“捕獲”了props。這樣,在它內(nèi)部的任何代碼(包括)都保證可以得到這一次特定渲染所使用的props。上面的例子是正確的,但是看起來(lái)很奇怪。如果你在方法中定義各種函數(shù),而不是使用class的方法,那么使用類(lèi)的意義在哪里?

所以這個(gè)時(shí)候我們就明白了函數(shù)式組件和類(lèi)組件的區(qū)別:

function ProfilePage({ user }) {
  const showMessage = () => {
    alert('Followed ' + user);
  };
  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };
  return (
    <button onClick={handleClick}>Follow</button>
  );
}

當(dāng)父組件使用不同的props來(lái)渲染時(shí),React會(huì)再次調(diào)用函數(shù)。但是我們點(diǎn)擊的事件處理函數(shù),"屬于"具有自己的值的上一次渲染,并且回調(diào)函數(shù)也能讀取到這個(gè)值。它們都保持完好無(wú)損。

三、區(qū)分useState與useRef的使用

使用Hooks,同樣的原則也適用于狀態(tài)。看這個(gè)例子:

function MessageThread() {
  const [message, setMessage] = useState('');
  const showMessage = () => {
    alert('You said: ' + message);
  };
  const handleSendClick = () => {
    setTimeout(showMessage, 3000);
  };
  const handleMessageChange = (e) => {
    setMessage(e.target.value);
  };
  return (
    <>
      <input value={message} onChange={handleMessageChange} />
      <button onClick={handleSendClick}>Send</button>
    </>
  );
}

如果我發(fā)送一條特定的消息,組件不應(yīng)該對(duì)實(shí)際發(fā)送的是哪條消息感到困惑。這個(gè)函數(shù)組件的變量捕獲了我們?cè)跒g覽器中執(zhí)行單擊處理函數(shù)的那一次渲染。所以當(dāng)我點(diǎn)擊“發(fā)送”時(shí)那一刻輸入框中的內(nèi)容就會(huì)被設(shè)置為彈出的值。

因此我們知道,在默認(rèn)情況下React中的函數(shù)會(huì)捕獲props和state。但是如果我們想要讀取并不屬于這一次特定渲染的,最新的props和state呢?

在函數(shù)式組件中,你也可以擁有一個(gè)在所有的組件渲染幀中共享的可變變量。它被成為“ref”:

function MyComponent() {
  const ref = useRef(null);
  // 你可以通過(guò) ref.current 來(lái)獲取保存的值.
  // ...
}

在很多情況下,你并不需要它們,并且分配它們將是一種浪費(fèi)。但是,如果你愿意,你可以這樣手動(dòng)地來(lái)追蹤這些值:

function MessageThread() {
  const [message, setMessage] = useState('');
  const latestMessage = useRef('');
  const showMessage = () => {
    alert('You said: ' + latestMessage.current);
  };
  const handleSendClick = () => {
    setTimeout(showMessage, 3000);
  };
  const handleMessageChange = (e) => {
    setMessage(e.target.value);
    latestMessage.current = e.target.value;
  };

如果我們?cè)?state 中讀取,我們將得到在我們按下發(fā)送按鈕那一刻的信息。但是當(dāng)我們通過(guò) ref 讀取時(shí),我們將得到最新的值,即使我們?cè)诎聪掳l(fā)送按鈕后繼續(xù)輸入。

通常情況下,你應(yīng)該避免在渲染期間讀取或者設(shè)置refs,因?yàn)樗鼈兪强勺兊?。我們希望保持渲染的可預(yù)測(cè)性。然而,如果我們想要特定props或者state的最新值,那么手動(dòng)更新ref會(huì)有些煩人。我們可以通過(guò)使用一個(gè)effect來(lái)自動(dòng)化實(shí)現(xiàn)它:

function MessageThread() {
  const [message, setMessage] = useState('');
  // 保持追蹤最新的值。
  const latestMessage = useRef('');
  useEffect(() => {
    latestMessage.current = message;
  });
  const showMessage = () => {
    alert('You said: ' + latestMessage.current);
  };

正如我們上面看到的,閉包實(shí)際上幫我們解決了很難注意到的細(xì)微問(wèn)題。同樣,它們也使得在并發(fā)模式下能更輕松地編寫(xiě)能夠正確運(yùn)行的代碼。這是可行的,因?yàn)榻M件內(nèi)部的邏輯在渲染它時(shí)捕獲并包含了正確的props和state。

React函數(shù)總是捕獲他們的值 —— 現(xiàn)在我們也知道這是為什么了。

到此這篇關(guān)于React函數(shù)組件與類(lèi)的區(qū)別有哪些的文章就介紹到這了,更多相關(guān)React函數(shù)組件與類(lèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React常見(jiàn)跨窗口通信方式實(shí)例詳解

    React常見(jiàn)跨窗口通信方式實(shí)例詳解

    這篇文章主要為大家介紹了React常見(jiàn)跨窗口通信方式實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 深入研究React中setState源碼

    深入研究React中setState源碼

    這篇文章主要介紹了深入研究React中setState源碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • React State與生命周期詳細(xì)介紹

    React State與生命周期詳細(xì)介紹

    React將組件(component)看成一個(gè)狀態(tài)機(jī)(State Machines),通過(guò)其內(nèi)部自定義的狀態(tài)(State)和生命周期(Lifecycle)實(shí)現(xiàn)并與用戶(hù)交互,維持組件的不同狀態(tài)
    2022-08-08
  • Remix?路由模塊輸出對(duì)象handle函數(shù)

    Remix?路由模塊輸出對(duì)象handle函數(shù)

    這篇文章主要為大家介紹了Remix?路由模塊輸出對(duì)象handle函數(shù)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • React初始化渲染過(guò)程示例詳解

    React初始化渲染過(guò)程示例詳解

    這篇文章主要為大家介紹了React初始化渲染過(guò)程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Vite+React+TypeScript手?jǐn)]TodoList的項(xiàng)目實(shí)踐

    Vite+React+TypeScript手?jǐn)]TodoList的項(xiàng)目實(shí)踐

    本文主要介紹了Vite+React+TypeScript手?jǐn)]TodoList的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • React中實(shí)現(xiàn)父組件調(diào)用子組件的三種方法

    React中實(shí)現(xiàn)父組件調(diào)用子組件的三種方法

    在React中,組件之間的通信是一個(gè)常見(jiàn)的需求,有時(shí),我們需要從父組件調(diào)用子組件的方法,這可以通過(guò)幾種不同的方式實(shí)現(xiàn),需要的朋友可以參考下
    2024-04-04
  • React虛擬列表的實(shí)現(xiàn)代碼

    React虛擬列表的實(shí)現(xiàn)代碼

    最近看了vueuse的useVirtualList的實(shí)現(xiàn)方式,發(fā)現(xiàn)虛擬滾動(dòng)效果不錯(cuò),就嘗試著同樣的寫(xiě)法改成react版本,虛擬列表主要包含三部分組成,offset,viewcapacity,overscan,本文就給大家介紹一下React虛擬列表的實(shí)現(xiàn),需要的朋友可以參考下
    2023-08-08
  • react+react-beautiful-dnd實(shí)現(xiàn)代辦事項(xiàng)思路詳解

    react+react-beautiful-dnd實(shí)現(xiàn)代辦事項(xiàng)思路詳解

    這篇文章主要介紹了react+react-beautiful-dnd實(shí)現(xiàn)代辦事項(xiàng),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • React Hook 父子組件相互調(diào)用函數(shù)方式

    React Hook 父子組件相互調(diào)用函數(shù)方式

    這篇文章主要介紹了React Hook 父子組件相互調(diào)用函數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09

最新評(píng)論

城市| 玛纳斯县| 丹阳市| 通州区| 元氏县| 广州市| 外汇| 灵寿县| 小金县| 台州市| 滨州市| 宣城市| 扎鲁特旗| 安国市| 达尔| 同德县| 青海省| 泸州市| 舟山市| 墨玉县| 乐都县| 蒲江县| 磐安县| 离岛区| 全州县| 赤峰市| 华池县| 自治县| 太原市| 衡东县| 和顺县| 汶川县| 长治县| 汤阴县| 林芝县| 曲沃县| 涟源市| 八宿县| 淅川县| 堆龙德庆县| 石屏县|