瞭解一個React組件

也能夠在這裏看:http://leozdgao.me/liao-jie-ge-reactzu-jian/html

最近React,這個專一View層的庫格外火熱,我我的已經探索了一段時間,原本一直想寫一些文字,總結下React應用開發和webpack構建工具的經驗。不過懶癌復發,一直沒動筆。前段時間給團隊安利這個庫,如今要開始用它寫項目了,因此本身挖的坑要填上,就開始寫一些基本的東西,就先從介紹React組件的基礎開始。react

從一個簡單的組件開始

標題叫「一個簡單的組件」,因而先來看下官方網站上一個叫作「A Simple Component」的例子來感覺下:webpack

var HelloMessage = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>
  }
})
React.render(<HelloMessage name="John" />, mountNode)

好的,經過React提供的工廠方法,咱們建立了一個組件,在這裏,咱們認爲createClass建立了一張blueprint,而經過jsx語法建立的<HelloMessage name="John" />則返回一個ReactElement對象來具體地告訴React要如何渲染組件(由於除了blueprint之外還須要一些外部狀態的傳入),這等同於調用React.createElement(HelloMessage, { name: 'John' }, 'Hello ', this.props.name)web

以後,React就能夠根據ReactElement對象,把組件掛載到頁面的某個節點上去,也就是React.render方法在作的事情,這個方法返回一個組件的實例,同時也意味着你能夠在已有項目中的一小部分嘗試React。api

下面來具體介紹下。瀏覽器

JSX

上面的例子裏看着像是把HTML寫在了Js裏,其實是經過一種更加清晰易讀且易維護的語法JSX來建立ReactElement對象。對React來講JSX是可選的,若是真的不喜歡也能夠用React.createElement這個api。babel

固然有JSX語法的js文件是不能直接在瀏覽器中運行的,咱們能夠用官方的JSXTransformer或者是babel來轉換。函數

須要注意的是classfor這兩個HTML屬性,因爲組件的屬性實際是以對象形式傳遞的,好比上面的{ name: 'John' },另外js不容許關鍵字做爲屬性名,因此須要分別用classNamehtmlFor代替。工具

建立一個組件

建立組件的時候須要給React.createClass提供一個對象,這個對象必須包含一個render方法和若干可選的生命週期方法。性能

要注意的是咱們須要保證render函數是純函數,即一樣的輸入始終返回相同的輸出,而且執行過程當中沒有反作用(和DOM交互或者發Ajax請求)。但一個組件要和DOM交互或者發Ajax請求需求是很正常的,那麼就要用到其餘生命週期方法了。

除此以外,更重要的部分是,讓一個組件能夠工做除了有blueprint外,還須要組件狀態。對於一個React組件來講,分爲不可變狀態this.props和可變狀態this.states

咱們能夠經過this.props決定一個組件內的部分呈現內容,好比上例中咱們但願呈現的名字是John,且不會改變。然而對於一個DropDownList而言,僅在點擊它時,一個下拉列表纔會顯示出來,那麼咱們認爲這個下拉列表是否顯示就是一個可變狀態。

說到可變狀態,那麼要這麼變?React並不但願咱們直接修改this.states,咱們須要使用this.setState的方式修改狀態,由於每次調用this.setStaterender方法都會被再次調用,同時也會調用一些相關的生命週期函數。this.setState接受一個對象做爲新狀態的patch,也就是說這個對象不會覆蓋現有的this.states,而是一個相似extend的行爲。

咱們也能夠提供一些默認狀態:

getDefaultProps () {
  return {
    name: 'defaultName'
  };
},
getInitialState: function() {
  return {
    listShowed: false
  };
},

其中getDefaultProps僅會被調用一次,這裏的意思是不管你會建立多少個ReactElement,這個函數都只執行一次,以後的默認props都會直接使用改函數的返回值。

這裏須要提一下React提供以ES6的方式建立組件,有意思的是ES6的版本用的是React.Component,在語意上比createClass更加明確。getDefaultPropsgetInitialState在ES6的版本中有些不太同樣,相對與getDefaultProps,ES6將默認屬性對象做爲了構造函數的一個屬性,而getInitialState則變成了在其構造器函數中給this.state賦值,來看一個栗子:

class HelloMessage extends React.Component {
  constructor (props) {
    this.super(props)
    this.state = {  } // 初始化狀態
  }
  render () {
    return <div>Hello {this.props.name}</div>
  }
}
HelloMessage.defaultProps = { name: 'defaultName' }

組件的生命週期

以前的部分一直有提到生命週期函數,下面就來介紹下:

componentWillMount會在組件即將被掛載時調用,此時this.refs對象爲空對象。若是在該函數中使用this.setState,那麼會更新this.states對象,而render依然只會調用一次,至關因而能夠覆蓋getInitialState返回的對象,雖然我以爲這沒什麼意義。

componentDidMount是很是經常使用的生命週期方法,僅當組件被掛載後調用一次,這意味着能夠在這個函數中進行一些DOM操做等,好比但願組件中的一個textbox能夠再掛載後自動獲取焦點:

componentDidMount () {
  const textbox = React.findDOMNode(this.refs.text)
  if (this.props.autoFocus) textbox.focus()
}

componentWillReceiveProps在將要接受新的props時被調用,不是說props是不可變狀態嗎?狀況一般是這樣的,當一個父組件包含了一個子組件,子組件的一個props的值是父組件的states的值,那麼當父組件可變狀態改變時,子組件的props也更新了,因而調用了這個函數。

componentWillReceiveProps (nextProps) {
  if (this.props.disabled !== nextProps.disabled) {
    // disabled這個屬性改變了
  }
}

這個生命週期函數componentWillReceiveProps提供了更新states的機會,能夠調用this.setState,也是惟一能夠在組件更新週期中調用this.setState的函數。

shouldComponentUpdate是在更新前根據該函數的返回值決定是否進行此次更新。

shouldComponentUpdate (nextProps, nextState) {
    // 比較props或者states,返回true則更新照常,返回false則取消更新,且不會調用下面的兩個生命週期函數
}

考慮這種狀況:父組件有子組件A和子組件B,當父組件調用this.setState更新一個做爲子組件A屬性的state時,render方法被再次調用,此時組件A和組件B同時被更新,其實真正改變的只有組件A,但組件B也同時被要求更新了,這是沒有必要的,因而shouldComponentUpdate就顯的有用了,在該函數體內比較props或是states,若是沒有改變就取消這個更新,這對性能上算是一個提高。

但若是是複雜對象的比較就比較麻煩了,由於咱們沒法經過===來判斷兩個對象的鍵值是否都相等,因而咱們就但願咱們的對象是不可變的(immutable)。這裏再也不展開了,你們能夠先自行探索,以後再寫這個部分的文字,並介紹immutable.js

componentWillUpdate在組件被更新前調用一次,能夠用來作一些更新前的準備工做,舉個栗子:

componentWillUpdate (nextProps, nextState) {
  if (!this.props.isShowed && nextProps.isShowed) {
    // 好比下拉菜單此時變的顯示了,能夠對此監聽一些事件什麼的
  }

  if (this.props.isShowed && !nextProps.isShowed) {
    // 好比下拉菜單隱藏了,能夠在這裏取消事件監聽
  }
}

(組件更新前事情還蠻多的...)

componentDidUpdate在組件更新完成後調用,能夠考慮在這個函數中執行一些DOM操做什麼的。

注意:絕對不要在componentWillUpdatecomponentDidUpdate中調用this.setState方法,不然將致使無限循環調用。

componentWillUnmount會在組件即將從掛載點移去時調用,此方法專門用來『擦屁股』,好比去除即將被銷燬的DOM節點的引用,或者是清除計時器,取消監聽的時間等等。


好了,正文結束,這一篇介紹了React比較基礎的部分,但願對你們有幫助,以後還會有一些更有針對性的部分。如文章中內容有誤,還請指正。

相關文章
相關標籤/搜索