組件的概念在Web中應用的場景已經相當廣泛了。愛掏網 - it200.com而React是專注于View層的,組件也是React核心理念之一,一個完整的應用將由一個個獨立的組件拼裝而成。愛掏網 - it200.com組件也是React最基礎的一部分,欲想征服React,那么了解和編寫組件就顯得尤為重要。愛掏網 - it200.com
在上一篇文章,咱們就寫了一個最簡單的React組件,而且在文章末尾,咱們留了一個問題,怎么創建無狀態和有狀態的React組件?接下來,就一起來了解React中的無狀態和有狀態的組件。愛掏網 - it200.com
在了解React中的無狀態和有狀態的組件之前,先來了解在React中創建組件的姿勢。愛掏網 - it200.com簡單的說,在React中創建組件有三種方式:
- ES5寫法:
React.createClass
- ES6寫法:
React.Component
- 無狀態的函數寫法,又稱為純組件SFC
React.createClass
React.createClass
是React剛開始推薦的創建組件的方式。愛掏網 - it200.com這是ES5的原生的JavaScript來實現的React組件。愛掏網 - it200.comReact.createClass
這個方法構建一個組件“類”,它接受一個對象為參數,對象中必須聲明一個render()
方法,render()
方法將返回一個組件實例。愛掏網 - it200.com
先來看一個React.createClass
創建組件的形式:
import React from 'react'
import ReactDOM from 'react-dom'
const SwitchButton = React.createClass({
getDefaultProp:function() {
return { open: false }
},
getInitialState: function() {
return { open: this.props.open };
},
handleClick: function(event) {
this.setState({ open: !this.state.open });
},
render: function() {
var open = this.state.open,
className = open ? 'switch-button open' : 'btn-switch';
return (
);
}
});
ReactDOM.render(
,
document.getElementById('root')
);
React.createClass
是用來創建有狀態的組件,這些組件是要被實例化的,并且可以訪問組件的生命周期方法。愛掏網 - it200.com不過React.createClass
創建React組件有其自身的問題存在:
-
React.createClass
會自動綁定函數方法,導致不必要的性能開銷,增加代發過時的可能性 -
React.createClass
的mixins
不夠自然、直觀
React.Component
React.Component
是以ES6的形式來創建React組件,也是現在React官方推薦的創建組件的方式,其和React.createClass
創建的組件一樣,也是創建有狀態的組件。愛掏網 - it200.com而且React.Component
最終會取代React.createClass
。愛掏網 - it200.com
把上面的例子,用React.Component
來修改:
import React from 'react'
import ReactDOM from 'react-dom'
class SwitchButton extends React.Component {
constructor(props) {
super(props)
this.state = {
open: this.props.open
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(event) {
this.setState({ open: !this.state.open })
}
render() {
let open = this.state.open,
className = open ? 'switch-button open' : 'btn-switch'
return (
)
}
}
SwitchButton.defaultProps = {
open: false
}
ReactDOM.render(
,
document.getElementById('root')
)
React.Component
和React.createClass
創建組件有蠻多不同之處,有關于這兩者的區別,@toddmotto去年就寫過一篇《React.createClass
versus extends React.Component
》,文章對兩者之間做過詳細的闡述。愛掏網 - it200.com
無狀態的函數寫法
無狀態的函數創建的組件是無狀態組件,它是一種只負責展示的純組件:
function HelloComponent(props) {
return Hello {props.name}
}
ReactDOM.render( , mountNode)
對于這種無狀態的組件,使用函數式的方式聲明,會使得代碼的可讀性更好,并能大大減少代碼量,箭頭函數則是函數式寫法的最佳搭檔:
const Todo = (props) => (
{props.text}
)
上面定義的 Todo
組件,輸入輸出數據完全由props
決定,而且不會產生任何副作用。愛掏網 - it200.com對于props
為 Object
類型時,我們還可以使用 ES6 的解構賦值:
const Todo = ({ onClick, complete, text, ...props }) => (
{props.text}
)
無狀態組件一般會搭配高階組件(簡稱:HOC)一起使用,高階組件用來托管state
,Redux 框架就是通過 store
管理數據源和所有狀態,其中所有負責展示的組件都使用無狀態函數式的寫法。愛掏網 - it200.com
這種模式被鼓勵在大型項目中盡可能以簡單的寫法 來分割原本龐大的組件,而未來 React 也會面向這種無狀態的組件進行一些專門的優化,比如避免無意義的檢查或內存分配。愛掏網 - it200.com所以建議大家盡可能在項目中使用無狀態組件。愛掏網 - it200.com
無狀態組件內部其實是可以使用ref
功能的,雖然不能通過this.refs
訪問到,但是可以通過將ref
內容保存到無狀態組件內部的一個本地變量中獲取到。愛掏網 - it200.com
例如下面這段代碼可以使用ref
來獲取組件掛載到DOM中后所指向的DOM元素:
function TestComp(props){
let ref;
return (
ref = node}>
)
}
如何選擇創建組件的方式
Facebook 官方早就聲明 ES6 React.Component
將取代React.createClass