新手写 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 组件的编写思路,你能够选择把你的组件编写成任意一种,那么使用者使用时也会有所不一样。可是做为一个具备良好可用性的组件,不该该限制使用者的用法,那么下篇将介绍如何编写一个既能够做为可控组件,也能够做为一个非可控组件的组件写法。