瞭解一個React元件
最近React,這個專注View層的庫格外火熱,我個人已經探索了一段時間,本來一直想寫一些文字,總結下React應用開發和webpack構建工具的經驗。不過懶癌復發,一直沒動筆。前段時間給團隊安利這個庫,現在要開始用它寫專案了,所以自己挖的坑要填上,就開始寫一些基本的東西,就先從介紹React元件的基礎開始。
從一個簡單的元件開始
標題叫“一個簡單的元件”,於是先來看下官方網站上一個叫做“A Simple Component”的例子來感受下:
var HelloMessage = React.createClass({ render: function() { returnHello {this.props.name}} }) React.render(, mountNode)
好的,透過React提供的工廠方法,我們建立了一個元件,在這裡,我們認為createClass
建立了一張blueprint,而透過jsx語法建立的
則返回一個ReactElement
物件來具體地告訴React要如何渲染元件(因為除了blueprint以外還需要一些外部狀態的傳入),這等同於呼叫React.createElement(HelloMessage, { name: 'John' }, 'Hello ', this.props.name)
。
之後,React就可以根據ReactElement
物件,把元件掛載到頁面的某個節點上去,也就是React.render
方法在做的事情,這個方法返回一個元件的例項,同時也意味著你可以在已有專案中的一小部分嘗試React。
下面來具體介紹下。
JSX
上面的例子裡看著像是把HTML寫在了Js裡,實際上是透過一種更加清晰易讀且易維護的語法JSX來建立ReactElement
物件。對React來說JSX是可選的,如果真的不喜歡也可以用React.createElement
這個api。
當然有JSX語法的js檔案是不能直接在瀏覽器中執行的,我們可以用官方的JSXTransformer
或者是babel
來轉換。
需要注意的是class
和for
這兩個HTML屬性,由於元件的屬性實際是以物件形式傳遞的,比如上面的{ name: 'John' }
,另外js不允許關鍵字作為屬性名,所以需要分別用className
和htmlFor
代替。
建立一個元件
建立元件的時候需要給React.createClass
提供一個物件,這個物件必須包含一個render
方法和若干可選的生命週期方法。
要注意的是我們需要保證render
函式是純函式,即同樣的輸入始終返回相同的輸出,並且執行過程中沒有副作用(和DOM互動或者發Ajax請求)。但一個元件要和DOM互動或者發Ajax請求需求是很正常的,那麼就要用到其他生命週期方法了。
除此之外,更重要的部分是,讓一個元件可以工作除了有blueprint外,還需要元件狀態。對於一個React元件來說,分為不可變狀態this.props
和可變狀態this.states
。
我們可以透過this.props
決定一個元件內的部分呈現內容,比如上例中我們希望呈現的名字是John,且不會改變。然而對於一個DropDownList
而言,僅在點選它時,一個下拉選單才會顯示出來,那麼我們認為這個下拉選單是否顯示就是一個可變狀態。
說到可變狀態,那麼要這麼變?React並不希望我們直接修改this.states
,我們需要使用this.setState
的方式修改狀態,因為每次呼叫this.setState
,render
方法都會被再次呼叫,同時也會呼叫一些相關的生命週期函式。this.setState
接受一個物件作為新狀態的patch,也就是說這個物件不會覆蓋現有的this.states
,而是一個類似extend的行為。
我們也可以提供一些預設狀態:
getDefaultProps () { return { name: 'defaultName' }; },getInitialState: function() { return { listShowed: false }; },
其中getDefaultProps
僅會被呼叫一次,這裡的意思是無論你會建立多少個ReactElement
,這個函式都只執行一次,之後的預設props
都會直接使用改函式的返回值。
這裡需要提一下React提供以ES6的方式建立元件,有意思的是ES6的版本用的是React.Component
,在語意上比createClass
更加明確。getDefaultProps
和getInitialState
在ES6的版本中有些不太一樣,相對與getDefaultProps
,ES6將預設屬性物件作為了建構函式的一個屬性,而getInitialState
則變成了在其構造器函式中給this.state
賦值,來看一個栗子:
class HelloMessage extends React.Component { constructor (props, context) { super(props, context) this.state = { } // 初始化狀態 } render () { returnHello {this.props.name}} } 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操作什麼的。
注意:絕對不要在componentWillUpdate
和componentDidUpdate
中呼叫this.setState
方法,否則將導致無限迴圈呼叫。
componentWillUnmount
會在元件即將從掛載點移去時呼叫,此方法專門用來『擦屁股』,比如去除即將被銷燬的DOM節點的引用,或者是清除計時器,取消監聽的時間等等。
好了,正文結束,這一篇介紹了React比較基礎的部分,希望對大家有幫助,之後還會有一些更有針對性的部分。如文章中內容有誤,還請指正。
作者:leozdgao
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4289/viewspace-2802727/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- table 元件瞭解一下?元件
- React-HOC瞭解一下React
- react-router瞭解一下React
- react 第一個元件 “hello world!”React元件
- 如何編寫一個React元件React元件
- react實現一個button元件React元件
- 手寫一個 React 動畫元件React動畫元件
- react篇章-React 元件-ES6 class 來定義一個元件React元件
- 如何用React寫一個Modal元件React元件
- React(0.13) 定義一個checked元件React元件
- React(0.13)定義一個checked元件React元件
- 元件化開發瞭解一下?元件化
- 後生,React-Hooks瞭解一下ReactHook
- 開發一個 React Loading 元件React元件
- 一個輕量級react埋點元件React元件
- 一個可拖拽的React標籤元件React元件
- 如何基於 React 封裝一個元件React封裝元件
- 使用 React 實現一個輪播元件React元件
- 快速瞭解 React Hooks 原理ReactHook
- 從Preact瞭解一個類React的框架是怎麼實現的(一): 元素建立React框架
- 一個提取圖片顏色的React元件React元件
- ? 黃瓜 UI: 一個即插即用的 React 元件庫UIReact元件
- 使用React手寫一個手風琴元件React元件
- React(0.13)定義一個多選的元件React元件
- 1 元件化的瞭解元件化
- 瞭解React Hooks及其常用的幾個鉤子函式ReactHook函式
- 分享一個自己開發的 react拖拽排序元件React排序元件
- 一個簡單的構建React元件動畫方案React元件動畫
- 釋出你的第一個 React 元件到 npmReact元件NPM
- React Native元件篇(一) — Text元件React Native元件
- 深入瞭解React新引擎:ReactFiberReact
- 從Preact瞭解一個類React的框架是怎麼實現的(二): 元素diffReact框架
- React效能優化的8種方式瞭解一下?React優化
- 可配置元件庫Fusion Design 瞭解一下元件
- react如果你想為一個元件返回多個元素怎麼辦?React元件
- React 實現一個簡單實用的 Form 元件ReactORM元件
- 使用npm釋出一個react元件(踩坑實踐)NPMReact元件
- 動手擼元件系列 —— 1. 使用React實現一個Collapse元件元件React