React 组件创建的三种形式

  • 函数式定义的无状态组件
  • es5原生方式React.createClass定义的组件
  • es6形式的extends React.Component定义的组件

无状态函数式组件

创建无状态函数式组件形式是从React 0.14版本开始出现的。它是为了创建纯展示组件,这种组件只负责根据传入的props来展示,不涉及到要state状态的操作。具体的无状态函数式组件,其官方指出:
在大部分React代码中,大多数组件被写成无状态的组件,通过简单组合可以构建成其他的组件等;这种通过多个简单然后合并成一个大应用的设计模式被提倡。

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

1.组件不会被实例化,整体渲染性能得到提升

因为组件被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会在有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。

2.组件不能访问this对象

无状态组件由于没有实例化过程,所以无法访问组件this中的对象,例如:this.ref、this.state等均不能访问。若想访问就不能使用这种形式来创建组件

3.组件无法访问生命周期的方法

因为无状态组件是不需要组件生命周期管理和状态管理,所以底层实现这种形式的组件时是不会实现组件的生命周期方法。所以无状态组件是不能参与组件的各个生命周期管理的。

4.无状态组件只能访问输入的props,同样的props会得到同样的渲染结果,不会有副作用

无状态组件被鼓励在大型项目中尽可能以简单的写法来分割原本庞大的组件,未来React也会这种面向无状态组件在譬如无意义的检查和内存分配领域进行一系列优化,所以只要有可能,尽量使用无状态组件。

es5原生方式React.createClass定义的组件

var Clock = React.createClass({
 propTypes: {//定义传入props中的属性各种类型
  initialValue: React.PropTypes.string
 },
 defaultProps: { //组件默认的props对象
  initialValue: new Date().toLocaleTimeString()
 },
 // 设置 initial state
 getInitialState: function() {//组件相关的状态对象
   return {
      text: this.props.initialValue
   };
 },
 componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
 },
 componentWillUnmount() {
    clearInterval(this.timerID);
 },
 tick() {
    this.setState({
      text: new Date().toLocaleTimeString()
    });
  },
 render: function() {
   return (
     <div>
      <h1>Hello, world!</h1>
      <h2>It is {this.state.text}</h2>
    </div>
   );
 }
});

ReactDOM.render(<Clock />, document.getElementById('root'))

与无状态组件相比,React.createClass和后面要描述的React.Component都是创建有状态的组件,这些组件是要被实例化的,并且可以访问组件的生命周期方法。但是随着React的发展,React.createClass形式自身的问题暴露出来:

  • React.createClass会自绑定函数方法(不像React.Component只绑定需要关心的函数)导致不必要的性能开销,增加代码过时的可能性。
  • React.createClass的mixins不够自然、直观;
const Contacts = React.createClass({ 
 handleClick() {
     console.log(this); 
 },
 render() {
     return (
         <div onClick={this.handleClick}>test</div>
     );
 }
});

ReactDOM.render(<Contacts />, document.getElementById('root'))
class Contacts extends React.Component { 
 constructor(props) {
     super(props);
 }
 handleClick() {
     console.log(this); // null
 }
 render() {
     return (
         <div onClick={this.handleClick}>test</div>
     );
}

ReactDOM.render(<Contacts />, document.getElementById('root'))

es6形式的extends React.Component定义的组件

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
Made with Slides.com