美文网首页react
React组件编写思路(一)

React组件编写思路(一)

作者: 唯泥Bernie | 来源:发表于2017-01-23 00:33 被阅读1739次

    新手写 React 组件往往无从入手,怎么写,什么时候用 props,什么时候用 state 摸不着头脑。其实是没有了解到 React 的一些思想。就我个人的经验大多数的组件都有一定的套路可言,接下来就先介绍下 React 组件的基本思想。

    React 组件可以分为可控组件和非可控组件。可控组件意思是组件自身控制自己的状态(属性),可以通过自身提供的方法(供调用者使用)来改变自己的状态。譬如一个 input text 输入框提供一个 reset 方法,如果要清空用户输入则通过获得 inupt 组件对象,然后调用 reset 方法来做

    refs.inputRef.rest() 。
    

    非可控组件的意思是组件本身的状态(属性)自己无法更改,只能随着外部传入的值(props)而变化。还是拿输入框清空这一个操作来说,非可控的 input 不通过自己提供方法来改变(维护)自己的状态(value),只通过外部传入一个值为空字符串的 value 来做到清空的效果。

    reset(){
      this.setState({
        inputValue: ''
      })
    }
    render(){
      return <input value={this.state.inputValue}/>
    }
    

    我们拿一个场景来看下完整的代码(一个 form 中有一个 input,有一个 reset 按妞,点击 reset 按妞会清空用户的输入),看下这两种组件书写的区别。
    受控组件例:

    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>
      }
    }
    

    非受控组件例:

    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。那么组件代码如下。

    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 的代码如下:

    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()。组件代码如下:

    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 把初始化状态在生成这个组件时传入,而不必等组件生成完再通过调用方法传入。于是修改后的代码如下:

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

    相关文章

      网友评论

      • shupingWei:楼主 你写反了。。受控组件指的是 可以通过state来控制的。。不可控的才是 通过原来那种dom操作。。

      本文标题:React组件编写思路(一)

      本文链接:https://www.haomeiwen.com/subject/pzzobttx.html