五分鐘,簡單聊一聊React Component的發展歷程

1、 前言

隨着 react 最新的一個大版本中,給咱們帶來了 Hooks:React v16.8: The One With Hooks,從而將 Function component 的能力提升了一大截,成功的擁有了能夠與 Class component 抗衡的能力。但話說回來,雖然 Hooks 看起來很美好,最近也有很多文章都講解了Hooks這一「黑魔法」,但技術的不斷演進,自己就是一個解決以往所存在問題的過程,所以我我的認爲着眼於如今,回望過去,去看一看 react component 的發展之路,去看看 Class component 以及 Function component 爲何會出現以及它們出現的意義,所要解決的問題,也對於咱們全面瞭解 react 是頗有幫助的。html

從 react component 的發展歷程上來看,它主要是經歷了一下三個階段:前端

  1. createClass Component
  2. Class Component
  3. Function Component

這個三個階段也是react的組件不斷走向輕量級的一個過程。其中 Class Component 徹底替代了 createClass Component 成爲了如今咱們開發 react 組件的主流,而 Function Component 也在 Hooks 推出後磨刀霍霍,準備大幹一場。下面就讓咱們去看看三者的具體狀況吧~react

注:這篇文章總體只是對React Component的發展歷程的一個歸納或者說是我本身學習後的一個整理,想要詳細瞭解,還請看看我在文章貼的那些連接。antd

2、 createClass Component

說實話,createClass Component 我也沒用過,由於我接觸到 react 的時候已是2017年下半年了,那時候 ES6 已經大行其道,class component 也已經徹底取代了 createClass Component。但如今看來 createClass Component 的語法也很簡單,並不複雜:ide

import React from 'react'

const MyComponent = React.createClass({
  // 經過proTypes對象和getDefaultProps()方法來設置和獲取props
  propTypes: {
    name: React.PropTypes.string
  },
  getDefaultProps() {
    return {

    }
  },
  // 經過getInitialState()方法返回一個包含初始值的對象
  getInitialState(){ 
        return {
            sayHello: 'Hello Srtian'
        }
    }
  render() {
    return (
      <p></p>
    )
  }
})

export default MyComponent
複製代碼

react.createClass的語法並不複雜,它經過 createClass 來建立一個組件,並經過propTypes和getDefaultProps來獲取props,經過經過getInitialState()方法返回一個包含初始值的對象,雖然從如今看來仍是有點麻煩,但整體上來看代碼也比較清晰,跟如今的 Class Component差異並非太大。但 react.createClass 自從 react 15.5版本就再也不爲 react 官方所推介,而是想讓你們的使用 class component 來代替它。並且在 react 16版本發佈後,createClass 更是被廢棄,當咱們使用它的時候,會提示報錯,也就是說,在 react 團隊看來 createClass 已經徹底沒有存在的必要了。函數

其實 Class Component 徹底替代 React.createClass 並非說 React.createClass 有多壞,相反它還有一些 class Component 所沒有的特性。它的廢棄是因爲ES6的出現,新增了 class 這一語法糖,讓咱們在 JavaScript 的開發中能夠直接使用 extends 來擴展咱們的對象,所以爲了與標準的ES6接軌,原有的只在 react 中使用的 createClass 天然而然也成爲了被拋棄的對象。但 class Component 在剛出現的時候也仍然存在的不小的爭議,由於這二者仍是存在必定的差異的,好比當時在Stack Overflow便出現了關於這二者的討論,感興趣的朋友能夠去看看:學習

stackoverflow.com/questions/3…測試

總的來講,除了語法上存在差別外,Class Component 和 React.createClass 的區別主要是如下兩點(詳情能夠看看上面的回答):ui

  • React.createClass 會正確綁定 this,而 React.Component 則不行,咱們須要在 constructor 裏面使用 bind 或者直接使用箭頭函數來綁定 this。
  • React.Component 不能使用 React mixins 特性,這一方面咱們可使用高階組件來彌補。

3、Class Component

Class Component建立的方式也很簡單,就是普通的ES6的class的語法,經過extends來建立一個新的對象來建立react組件,下面是使用class Component建立一個組件的例子(因爲爲了給後面聊一聊hooks,因此在這裏我使用了antd的例子)this

class Modal extends React.Component {
  state = { visible: false }

  showModal = () => {
    this.setState({
      visible: true,
    });
  }
  handleOk = (e) => {
    console.log(e);
    this.setState({
      visible: false,
    });
  }
  handleCancel = (e) => {
    console.log(e);
    this.setState({
      visible: false,
    });
  }
  render() {
    return (
      <div> <Button type="primary" onClick={this.showModal}> Open Modal </Button> <Modal title="Basic Modal" visible={this.state.visible} onOk={this.handleOk} onCancel={this.handleCancel} > <p>this is a modal</p> </Modal> </div>
    );
  }
}
複製代碼

上面就是antd中一個簡單的 modal 組件的例子,其內部就是經過維護 visible 的狀態來控制這個 modal 是否顯示。咱們能夠看到,其中的一些方法都是使用箭頭函數的方式來將 this 綁定到正確的屬性。(具體爲何要這麼作,不清楚的朋友能夠看看下面這篇文章:)

www.freecodecamp.org/news/this-i…

而相似於上面的這種組件,也是近兩年來咱們在平常開發中使用最多的組件開發的方式。那爲何到了如今,咱們又開始要強調使用 Function Component 來進行開發了呢?主要是因爲 Class Component 所開發的組件仍然存在如下一些問題:

  1. this 綁定的問題: 咱們前面也提到了,咱們在使用本來的 React.createClass 時並不須要去考慮this綁定的問題,而如今咱們卻要時刻注意使用bind或者箭頭函數來讓this正確綁定,同時也讓一些新上手react的同窗的上手成本有所提高。雖然這不是React的鍋,但這方面的問題仍然客觀存在。
  2. 嵌套地獄: 這種狀況則多發生於須要用到Context的場景下,在這種場景下,數據是同步的,由於須要通知更新全部有引用到數據的地方,所以咱們就須要經過render-props 的形式定義在Context.Consumer的children中,而使用到越多的Context 就會致使嵌套層級越多,這很容易讓人看代碼看的一臉懵逼。好比這樣:
<FirstContext.Consumer>
  {first => (
    <SecondContext.Consumer>
      {second => (
        <ThirdContext.Consumer>
          {third => (
            <Component />
          )}
        </ThirdContext.Consumer>
      )}
    </SecondContext.Consumer>
  )}
</FirstContext.Consumer>
複製代碼
  1. Life-cycles 的問題:生命週期函數也是咱們在平常開發所常用到的東西。雖然生命週期函數用起來很方便,但一旦組件的邏輯變得複雜起來,這些生命週期函數也會變得難以理解和維護;同時如何讓這些生命週期函數與react渲染有效結合也是一個不小的問題,這每每可能會讓一些剛上手的人摸不着頭腦。此外使用這些生命週期函數時也可能會出現一些預料以外的事情發生(好比在某些生命週期函數中進行數據請求,而致使組件被重複渲染屢次的問題等等,這些都是有可能發生的)

詳細能夠去看看知乎上的這個回答:www.zhihu.com/question/30…

4、Function Component

看到這裏,你們對class Component所存在的一些問題也算是有一些瞭解了,但爲何它還能橫行如此之久,一直佔據着主流的地位呢?其本質上就是由於沒有競爭對手嘛,Function Component 長期沒有內部狀態管理機制,只能經過外部來管理狀態,所以組件的可測試性很是的高,寫起來也簡潔明瞭,符合如今前端函數式的大潮流,是個好同志。但也正是由於沒有狀態管理機制,因此沒法和Class Component相抗衡,畢竟一旦組件內部的邏輯變得複雜以後,內部的狀態管理機制是必須的。

所以 React 團隊基於 Function Component 提出 Hooks 的概念,用以解決 Function Component 的內部狀態管理,同時也但願經過 Hooks 來解決 Class Component 所存在的問題。下面就是使用 Hooks 針對 antd 中的 modal 進行的改寫,你們能夠自行感覺一下:

const Modal = () => {
  const [visible , changeVisible] = useState(false)
  return (
    <div> <Button type="primary" onClick={()=>changeVisible(true)}>open</Button> <Modal title="Basic Modal" visible={visible} onOk={()=>changeVisible(false)} onCancel={()=>changeVisible(false)} > <p>this is a modal</p> </Modal> </div>
  )
}
複製代碼

咱們能夠看到,基於 Function Component 與 Hooks 所編寫出來的組件代碼是至關簡潔明瞭的,也直接避免了咱們上面所提到的 this 指向的問題。而對於上面所提到的嵌套地獄以及 Life-cycles 的問題,Hooks也提供了 useContext 和 useEffect(這個倒仍是存在一些問題) 來解決,在這裏我也不詳細說了,詳情能夠去看官方文檔或者是 Dan 的博客:

overreacted.io/a-complete-…

好了,看到這裏我想你們都覺得上面 Class Component 的問題都已經獲得圓滿解決了,Function Component好像已經圓滿了,咱們只管放心的使用它就行了。但世界上哪有這麼好的事情,Function Component 仍然存在着下面幾個 tip 是咱們在使用前要知道的:

  1. Function Component 與 Class Component 表現不一樣,這塊不清楚的能夠直接去看Dan的文章,他對這方面作了很明白的闡述:

overreacted.io/how-are-fun…

  1. 使用useState須要注意的是,它的執行順序要在每次 render 時必須保持一致,不能夠進判斷和循環,必須寫在最前面,關於這一點看視頻:

www.youtube.com/watch?v=dpw…

  1. Function Component 中,外部對與函數式組件的操做只能經過 props 來進行控制,不能經過函數式組件內部暴露方法來對組件進行操做。

參考資料:

相關文章
相關標籤/搜索