新手寫 React 組件每每無從入手,怎麼寫,何時用 props,何時用 state 摸不着頭腦。實際上是沒有了解到 React 的一些思想。就我我的的經驗大多數的組件都有必定的套路可言,接下來就先介紹下 React 組件的基本思想。javascript
React 組件能夠分爲可控組件和非可控組件。可控組件意思是組件自身控制本身的狀態(屬性),能夠經過自身提供的方法(供調用者使用)來改變本身的狀態。譬如一個 input text 輸入框提供一個 reset 方法,若是要清空用戶輸入則經過得到 inupt 組件對象,而後調用 reset 方法來作java
refs.inputRef.rest() 。
非可控組件的意思是組件自己的狀態(屬性)本身沒法更改,只能隨着外部傳入的值(props)而變化。仍是拿輸入框清空這一個操做來講,非可控的 input 不經過本身提供方法來改變(維護)本身的狀態(value),只經過外部傳入一個值爲空字符串的 value 來作到清空的效果。ajax
reset(){ this.setState({ inputValue: '' }) } render(){ return <input value={this.state.inputValue}/> }
咱們拿一個場景來看下完整的代碼(一個 form 中有一個 input,有一個 reset 按妞,點擊 reset 按妞會清空用戶的輸入),看下這兩種組件書寫的區別。
受控組件例:ide
class App extends React.Component { reset = ()=>{ this.refs.myInput.reset() // 假設 input 有一個 reset 方法 } render() { <div> <form> <input type="text" ref="myInput" /> <button onClick={ this.reset }>Reset</button> </form> </div> } }
非受控組件例:this
class App extends React.Component { constructor( props ){ super( props ); this.state = { inputValue: 'Plz input your text.' } } reset = ()=>{ this.setState( { inputValue: '' } ) } render() { <div> <form ref="myForm"> <input type="text" value={ this.state.inputValue }/> <button onClick={ this.reset }>Reset</button> </form> </div> } }
接下來咱們來看下若是編寫這兩種組件,打個比方咱們要自定義一個 alert 組件。咱們先從非受控組件提及,由於較簡單。非受控組件所要作的就是把全部狀態提取到組件的 props 中去,render 中就用 props。一個 alert 有哪些最基本的狀態(屬性)呢?咱們以最基礎的功能定出一個表示顯示與否的 show,一個表示顯示內容的 content。那麼組件代碼以下。rest
class Alert extends React.Component { constructor( props ) { super( props ) } render() { let style = { display: this.props.show ? 'fixed' : 'none' } return ( <div class="my-alert" style={ style } > <div class="my-alert-tit">Alert</div> <div>{ this.props.content }</div> <div class="my-alert-footer"> <button>肯定</button> </div> </div> ); } } Alert.propTypes = { show: React.PropTypes.bool, content: React.PropTypes.string }
咱們看到最直觀的就是隻須要考慮到 props 的可能取值就行,不須要關心如何改變props。而使用這個非可控 alert 的代碼以下:code
class App extends React.Component { constructor() { super(); this.state = { alertMsg: '', showAlert: false } this.saveHandler = ()=>{ // ajax success this.setState( { alertMsg: 'Save successfully', showAlert: true } ) } } render() { <div> <button onClick={ this.saveHandler }>Save</button> <Alert content={ this.state.alertMsg } show={ this.state.showAlert } /> </div> } }
接下來咱們看下可控組件的alert怎麼寫。可控組件經過方法來供調用者來改變組件的狀態(屬性)。因此暫時咱們不定義 props 只定義幾個方法 show(content), hide()。組件代碼以下:orm
class Alert extends React.Component { constructor( props ) { super( props ) this.state = { content: '', show: false } this.show = ( content )=>{ this.setState( { content: content, show: true } ) } this.hide = ()=>{ this.setState( { show: false } ) } } render() { let style = { display: this.state.show ? 'fixed' : 'none' } return ( <div class="my-alert" style={ style } > <div class="my-alert-tit">Alert</div> <div>{ this.state.content }</div> <div class="my-alert-footer"> <button onClick={ this.hide }>肯定</button> </div> </div> ); } }
咱們看到可控組件內部須要用到 state 來本身改變本身的狀態。使用這個可控 alert 的代碼以下:對象
import { Alert } from 'Alert'; class App extends React.Component { constructor() { super(); this.saveHandler = ()=>{ // ajax success this.refs.myAlert.show( 'Save Successfully' ); } } render() { <div> <button onClick={ this.saveHandler }>Save</button> <Alert ref="myAlert"/> </div> } }
可是可控組件有一個問題就是他的初始化狀態如何設置(如何由外部定義組件 state 的初始化值)?因爲沒有 props 那麼只能經過方法來設置,那麼這麼作法很彆扭。這時能夠經過定義 props 把初始化狀態在生成這個組件時傳入,而沒必要等組件生成完再經過調用方法傳入。因而修改後的代碼以下:ip
class Alert extends React.Component { constructor( props ) { super( props ) this.state = { content: this.props.defaultContent, show: this.props.defaultShow } this.show = ( content )=>{ this.setState( { content: content, show: true } ) } this.hide = ()=>{ this.setState( { show: false } ) } } render() { let style = { display: this.state.show ? 'fixed' : 'none' } return ( <div class="my-alert" style={ style } > <div class="my-alert-tit">Alert</div> <div>{ this.state.content }</div> <div class="my-alert-footer"> <button onClick={ this.hide }>肯定</button> </div> </div> ); } } Alert.propTypes = { defaultShow: React.PropTypes.bool, defaultContent: React.PropTypes.string } Alert.defaultProps = { defaultShow: false, defaultContent: '' }
使用這個組件的代碼:
class App extends React.Component { constructor() { super(); this.state = { alertMsg: '', showAlert: false } this.saveHandler = ()=>{ // ajax success this.refs.myAlert.show( 'Save Successfully' ); } } render() { <div> <button onClick={ this.saveHandler }>Save</button> <Alert ref="myAlert" defaultShow={false} defaultContent={''}/> </div> } }
以上就是兩種 React 組件的編寫思路,你能夠選擇把你的組件編寫成任意一種,那麼使用者使用時也會有所不一樣。可是做爲一個具備良好可用性的組件,不該該限制使用者的用法,那麼下篇將介紹如何編寫一個既能夠做爲可控組件,也能夠做爲一個非可控組件的組件寫法。