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

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

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

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

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

首先我們來看下面這個組件:

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

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

那么我們用類應(yīng)該怎么寫這個組件呢?一個簡單的重構(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)的時候都認為他們兩個是等效的,但是事實真的如此嗎,我們很少注意到它們之間的含義。

下面我們新建一個 react 項目,在 src下新建兩個組件,一個 classComponent 組件,一個是 functionComponent 組件。代碼就是上面我們寫的這兩個組件,只不過內(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 中我們將這兩個組件引入:

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

運行項目,科研看到這樣的界面:

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

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

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

2. 在點擊后立刻切換想要拜訪的朋友

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

頁面彈出的還是我們當時選擇的值

同樣的操作我們再試一下類組件:

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

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

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

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

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

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

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

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

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

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

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

一種方法是在調(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;

這種方法會起作用。然而,這種方法使得代碼明顯變得更加冗長,并且隨著時間推移容易出錯。如果我們需要的不止是一個props怎么辦?如果我們還需要訪問state怎么辦?

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

通常來說我們會避免使用閉包,但是在React中,props和state是不可變的,這就消除了閉包的一個主要缺陷。

這就意味著如果你在一次特定的渲染中捕獲那一次渲染所用的props或者state,你會發(fā)現(xiàn)他們總是會保持一致,就如同你的預(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>;
  }
}

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

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

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

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

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

使用Hooks,同樣的原則也適用于狀態(tài)??催@個例子:

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)該對實際發(fā)送的是哪條消息感到困惑。這個函數(shù)組件的變量捕獲了我們在瀏覽器中執(zhí)行單擊處理函數(shù)的那一次渲染。所以當我點擊“發(fā)送”時那一刻輸入框中的內(nèi)容就會被設(shè)置為彈出的值。

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

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

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

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

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;
  };

如果我們在 state 中讀取,我們將得到在我們按下發(fā)送按鈕那一刻的信息。但是當我們通過 ref 讀取時,我們將得到最新的值,即使我們在按下發(fā)送按鈕后繼續(xù)輸入。

通常情況下,你應(yīng)該避免在渲染期間讀取或者設(shè)置refs,因為它們是可變得。我們希望保持渲染的可預(yù)測性。然而,如果我們想要特定props或者state的最新值,那么手動更新ref會有些煩人。我們可以通過使用一個effect來自動化實現(xiàn)它:

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

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

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

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

相關(guān)文章

  • React常見跨窗口通信方式實例詳解

    React常見跨窗口通信方式實例詳解

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

    深入研究React中setState源碼

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

    React State與生命周期詳細介紹

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

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

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

    React初始化渲染過程示例詳解

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

    Vite+React+TypeScript手擼TodoList的項目實踐

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

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

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

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

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

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

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

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

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

最新評論

南投市| 保山市| 乌苏市| 山东省| 阿巴嘎旗| 中超| 泾川县| 信丰县| 雷波县| 兴隆县| 左权县| 金华市| 柘荣县| 宜阳县| 五莲县| 涡阳县| 仁寿县| 长垣县| 肇东市| 新巴尔虎右旗| 临颍县| 罗定市| 沭阳县| 阿鲁科尔沁旗| 勐海县| 获嘉县| 延庆县| 桐梓县| 临江市| 梁河县| 清徐县| 宜州市| 沙雅县| 庆元县| 都江堰市| 华安县| 延庆县| 巢湖市| 济源市| 赤水市| 弥勒县|