亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React中函數組件與類組件有什么區別

發布時間:2020-12-04 11:22:20 來源:億速云 閱讀:433 作者:小新 欄目:web開發

這篇文章給大家分享的是有關React中函數組件與類組件有什么區別的內容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。

區別:1、函數組件是一個純函數,它接收一個props對象返回一個react元素;而類組件需要去繼承React.Component并且創建render函數返回react元素。2、函數組件沒有生命周期和狀態state,而類組件有。

在本文中我將向你展示函數組件和類組件有什么不同,并且在編碼過程中應該如何選擇?

定義一個組件最簡單的方式就是使用JavaScript函數:

import React from 'react'
const Welcome = (props) => {
  return <h2>welcome, {props.name}</h2>
}
export default Welcome

這個函數接收一個props對象并返回一個react元素

你也可以使用ES6 class語法去寫一個組件:

import React from 'react'
class Welcome extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    return <h2>welcome, {this.props.name}</h2>
  }
}

export default Welcome

這兩個版本是等價的,它們具有相同的輸出。那么我們應該去選擇哪一種實現方式呢?下面我們來對他們進行比較

1、語法上

兩者最明顯的不同就是在語法上,函數組件是一個純函數,它接收一個props對象返回一個react元素。而類組件需要去繼承React.Component并且創建render函數返回react元素,這將會要更多的代碼,雖然它們實現的效果相同。

我們更深入的了解下,使用babel7分別對他們進行轉譯
函數組件轉譯結果:

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

var _react = _interopRequireDefault(require("react"));

var Welcome = function Welcome(props) {
  return _react["default"].createElement("h2", null, "welcome, ", props.name);
};

var _default = Welcome;
exports["default"] = _default;

類組件轉譯結果:

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));

var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

var _react = _interopRequireDefault(require("react"));

var Welcome =
/*#__PURE__*/
function (_React$Component) {
  (0, _inherits2["default"])(Welcome, _React$Component);

  function Welcome(props) {
    (0, _classCallCheck2["default"])(this, Welcome);
    return (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(Welcome).call(this, props));
  }

  (0, _createClass2["default"])(Welcome, [{
    key: "render",
    value: function render() {
      return _react["default"].createElement("h2", null, "welcome, ", this.props.name);
    }
  }]);
  return Welcome;
}(_react["default"].Component);

var _default = Welcome;
exports["default"] = _default;

可以看到類組件轉譯成ES5后代碼更多更長,但這不是區分它們的主要因素,僅僅了解一下。

2、狀態管理

因為函數組件是一個純函數,你不能在組件中使用setState(),這也是為什么把函數組件稱作為無狀態組件。

如果你需要在你的組件中使用state,你可以選擇創建一個類組件或者將state提升到你的父組件中,然后通過props對象傳遞到子組件。

3、生命周期鉤子

你不能在函數組件中使用生命周期鉤子,原因和不能使用state一樣,所有的生命周期鉤子都來自于繼承的React.Component中。

因此,如果你想使用生命周期鉤子,那么需要使用類組件。

注意:在react16.8版本中添加了hooks,使得我們可以在函數組件中使用useState鉤子去管理state,使用useEffect鉤子去使用生命周期函數。因此,2、3兩點就不是它們的區別點。從這個改版中我們可以看出作者更加看重函數組件,而且react團隊曾提及到在react之后的版本將會對函數組件的性能方面進行提升。

4、調用方式

如果SayHi是一個函數,React需要調用它:

// 你的代碼 
function SayHi() { 
    return <p>Hello, React</p> 
} 
// React內部 
const result = SayHi(props) // ? <p>Hello, React</p>

如果SayHi是一個類,React需要先用new操作符將其實例化,然后調用剛才生成實例的render方法:

// 你的代碼 
class SayHi extends React.Component { 
    render() { 
        return <p>Hello, React</p> 
    } 
} 
// React內部 
const instance = new SayHi(props) // ? SayHi {} 
const result = instance.render() // ? <p>Hello, React</p>

可想而知,函數組件重新渲染將重新調用組件方法返回新的react元素,類組件重新渲染將new一個新的組件實例,然后調用render類方法返回react元素,這也說明為什么類組件中this是可變的

5、獲取渲染時的值

這一點是他們最大差異,但又常常被人們忽略。

考慮以下組件:

function ProfilePage(props) {
  const showMessage = () => {
    alert('Followed ' + props.user);
  }

  const handleClick = () => {
    setTimeout(showMessage, 3000);
  }

  return (
    <button onClick={handleClick}>Follow</button>
  )
}

UserProfile組件很簡單,就一個Follow按鈕,該按鈕使用了setTimeout模擬網絡請求。用戶點擊這個按鈕之后會彈出一個警告框。如果props.user'Dan',它將在三秒鐘后顯示'Followed Dan'

我們如何將其編寫為類?天真的翻譯可能像這樣:

class ProfilePage extends React.Component {
  showMessage() {
    alert('Followed ' + this.props.user);
  }

  handleClick() {
    setTimeout(this.showMessage.bind(this), 3000);
  }

  render() {
    return <button onClick={this.handleClick.bind(this)}>Follow</button>
  }
}

通常認為這兩個代碼段是等效的。人們經常在這些模式之間自由重構,而沒有注意到它們的含義

但是,這兩個代碼段是完全不同的。好好看看他們。你看到區別了嗎?

分別按下面的順序來操作Follow按鈕:

  1. 先點擊Follow按鈕
  2. 3s之前更改下拉選擇項的選項
  3. 閱讀彈出的警告框內容

你會發現函數組件和類組件是有區別的:

函數組件:按上面所列的三個步驟操作時,當用戶在3s前更改下拉選擇框的選項時,h2的用戶名會立馬改變,而3s后彈出的警告框中的用戶名并不會改變

類組件:按上面所列的三個步驟操作時,當用戶在3s前更改下拉選擇框的選項時,h2中的用戶名會立馬改變,而3s后彈出的警告框中的用戶名也會改變

React中函數組件與類組件有什么區別

React中函數組件與類組件有什么區別

那么,為什么我們的類示例會這樣表現呢?

讓我們仔細看一下showMessage類中的方法:

showMessage() {
    alert('Followed ' + this.props.user);
  }

showMessage方法中讀取了this.props.user(也是我們要輸出的用戶名稱)。而React中的props是不可變的,但是this是可變的,而且是一直是可變的。這也是類組件中this的目的。React自身會隨著時間的推移對this進行修改,以便你可以在render函數或生命周期中讀取新的版本。

因此,如果組件在請求重新渲染時,this.props將會改變。showMessage方法會從新的props中讀取user。你所看到的效果也正是因為這個原因。

React中的組件,UI在概念上可以理解是程序當前狀態的函數,那么事件處理就是讓UI的渲染結果一部分一部分可視化輸出。我們的事件處理程序屬于具有特定propsstate的特定渲染。但是,當回調超時的話,this.props就會打破這種聯系。示例中的showMessage方法在回調時沒有綁定到任何特定的渲染,因此它會丟失真正的props

那么我們有沒有一種較好的方式可以使用正確的props來修復rendershowMessage回調之間的聯系。我們可以在事件發生的早期,將this.props傳遞給超時完成的處理程序來嘗試著解決這個問題。這種解決方式屬于閉包的范疇。

class ProfilePage extends React.Component {
  showMessage(user) {
    alert('Followed ' + user);
  }

  handleClick() {
    cosnt {user} = this.props
    setTimeout(this.showMessage.bind(this, user), 3000);
  }

  render() {
    return <button onClick={this.handleClick.bind(this)}>Follow</button>
  }
}

我們使用閉包機制將上一狀態的值保存下來待showMessage方法調用。即使this.props發生變化,但并不改變user

這種方法雖然解決我們前面所提到的問題,但是這種方法代碼會隨著props的個數增加,代碼也會變得更加冗余也易于出錯。如果我們也需要訪問state。如果showMessage調用另一個方法,該方法會讀取this.props.somethingthis.state.something。我們又會碰到同樣的問題。所以我們必須通過this.props作為showMessage的參數來修復它們之間存在的問題。

但這么做會破壞類提供的特性。也令人難于記住或執行。另外,在handleClick中內聯alert中的代碼并不能解決更大的問題。我們希望以一種允許代碼分解成更多方法的方式來構造代碼,同時還可以讀取與其相關的render所對應的propsstate

或許,我們可以在類的構造函數中綁定這些方法:

class ProfilePage extends React.Component {
  render() {
    // 獲取props
    cosnt props = this.props
    
    // 它們不是類方法
    const showMessage = () => {
        alert('Followed ' + props.user);
    }
    
    const handleClick = () => {
        setTimeout(showMessage, 3000)
    }
    
    return <button onClick={handleClick}>Follow</button>
  }
}

這樣一來,函數組件和類組件所達到的效果都一樣了。在類組件中可以捕獲渲染時的props。效果上看上去是一樣了,但看起來怪怪的。如果在類組件中的render中定義函數而不是使用類方法,那么還有使用類的必要性?

感謝各位的閱讀!關于React中函數組件與類組件有什么區別就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

杭锦旗| 南昌市| 汽车| 巴里| 宝山区| 湖州市| 临泉县| 翁源县| 南雄市| 建昌县| 金坛市| 嘉峪关市| 石阡县| 来宾市| 孙吴县| 故城县| 嵩明县| 卢龙县| 南乐县| 乌鲁木齐县| 汉阴县| 庆云县| 大邑县| 循化| 永平县| 汉源县| 奉节县| 花莲县| 阜康市| 青河县| 连州市| 思茅市| 百色市| 临清市| 乌兰浩特市| 华容县| 金湖县| 尚志市| 玛曲县| 合山市| 唐山市|