亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

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

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

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

那么我們用類應(yīng)該怎么寫這個(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 組件。代碼就是上面我們寫的這兩個(gè)組件,只不過內(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>歡迎來到 {this.state.user}的 家!</h1>
        <p>
          <ProfilePageFunction user={this.state.user} />
          <b> (這是來自函數(shù)式組件的)</b>
        </p>
        <p>
          <ProfilePageClass user={this.state.user} />
          <b> (這是來自類組件的)</b>
        </p>
      </>
    )
  }
}

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

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

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

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

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

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

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

同樣的操作我們?cè)僭囈幌骂惤M件:

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

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

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

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

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

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

事實(shí)上,這就是類組件存在的意義。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)并沒有與任何一個(gè)特定的渲染綁定在一起,所以它失去了正確的 props。

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

我們想要以某種方式“修復(fù)”擁有正確 props 的渲染與讀取這些 props 的回調(diào)之間的聯(lián)系。它們?cè)陬惖哪硞€(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怎么辦?如果我們還需要訪問state怎么辦?

然而,如果我們能利用JavaScript閉包的話問題將迎刃而解。

通常來說我們會(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。上面的例子是正確的,但是看起來很奇怪。如果你在方法中定義各種函數(shù),而不是使用class的方法,那么使用類的意義在哪里?

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

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

當(dāng)父組件使用不同的props來渲染時(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);
  // 你可以通過 ref.current 來獲取保存的值.
  // ...
}

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

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)我們通過 ref 讀取時(shí),我們將得到最新的值,即使我們?cè)诎聪掳l(fā)送按鈕后繼續(xù)輸入。

通常情況下,你應(yīng)該避免在渲染期間讀取或者設(shè)置refs,因?yàn)樗鼈兪强勺兊?。我們希望保持渲染的可預(yù)測(cè)性。然而,如果我們想要特定props或者state的最新值,那么手動(dòng)更新ref會(huì)有些煩人。我們可以通過使用一個(gè)effect來自動(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ì)微問題。同樣,它們也使得在并發(fā)模式下能更輕松地編寫能夠正確運(yùn)行的代碼。這是可行的,因?yàn)榻M件內(nèi)部的邏輯在渲染它時(shí)捕獲并包含了正確的props和state。

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

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

相關(guān)文章

  • react+redux的升級(jí)版todoList的實(shí)現(xiàn)

    react+redux的升級(jí)版todoList的實(shí)現(xiàn)

    本篇文章主要介紹了react+redux的升級(jí)版todoList的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • 在react中使用vuex的示例代碼

    在react中使用vuex的示例代碼

    這篇文章主要介紹了在react中使用vuex的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • 關(guān)于react-router-dom路由入門教程

    關(guān)于react-router-dom路由入門教程

    這篇文章主要介紹了關(guān)于react-router-dom路由入門教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • React?Suspense解決競(jìng)態(tài)條件詳解

    React?Suspense解決競(jìng)態(tài)條件詳解

    這篇文章主要為大家介紹了React?Suspense解決競(jìng)態(tài)條件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • React反向代理及樣式獨(dú)立詳解

    React反向代理及樣式獨(dú)立詳解

    這篇文章主要介紹了React反向代理及樣式獨(dú)立詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-08-08
  • 如何在 React 中調(diào)用多個(gè) onClick 函數(shù)

    如何在 React 中調(diào)用多個(gè) onClick 函數(shù)

    這篇文章主要介紹了如何在React中調(diào)用多個(gè)onClick函數(shù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • react中context傳值和生命周期詳解

    react中context傳值和生命周期詳解

    這篇文章主要介紹了react中context傳值和生命周期,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • React組件的創(chuàng)建與state同步異步詳解

    React組件的創(chuàng)建與state同步異步詳解

    這篇文章主要介紹了react組件實(shí)例屬性state,有狀態(tài)state的組件稱作復(fù)雜組件,沒有狀態(tài)的組件稱為簡(jiǎn)單組件,狀態(tài)里存儲(chǔ)數(shù)據(jù),數(shù)據(jù)的改變驅(qū)動(dòng)頁(yè)面的展示,本文結(jié)合實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2023-03-03
  • react echarts tooltip 區(qū)域新加輸入框編輯保存數(shù)據(jù)功能

    react echarts tooltip 區(qū)域新加輸入框編輯保存數(shù)據(jù)功能

    這篇文章主要介紹了react echarts tooltip 區(qū)域新加輸入框編輯保存數(shù)據(jù)功能,大概思路是用一個(gè)div包裹echarts, 然后在echarts的同級(jí)新建一個(gè)div用來用來模擬真實(shí)tooltip,通過鼠標(biāo)移入移出事件控制真實(shí)tooltip的顯示與隱藏,需要的朋友可以參考下
    2023-05-05
  • React如何以Hook的方式使用Echarts

    React如何以Hook的方式使用Echarts

    這篇文章主要介紹了React如何以Hook的方式使用Echarts問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評(píng)論