reactjs组件-基础篇

和很多人都是通过 reactjs 了解到 react native 不同,而我恰恰相反,15年上半年在进行hybrid 开发时了解了 react native 之后才开始接触 reactjs。而真正在项目中使用 reactjs 是从今年6月份开始,到现在这半年中开发的两个项目都是在使用reactjs。期间也遇到各种各样的问题,对 reactjs 了解也更加深入,就希望把自己学习到的一些分享给大家。


为何要了解 react 组件

react 开发的主要工作就是编写 react 组件,很多人也是通过官方的三分钟上手 react 的例子开始入坑的。只需要编写一个简单的组件,然后render之后就可以在浏览器中运行。 但是随着业务复杂度上升,需求和交互越来越复杂,编写组件就出现了各种各样的问题,这时候我们就需要更清楚地了解 react 组件。

如何创建 react 组件

创建 react component 主要有三种方式:

  1. 通过函数定义无状态的组件

  2. 通过 React.createClass 定义组件

  3. 通过继承 React.Component 定义组件

通过函数定义无状态组件

这种方式主要是为了创建纯展示组件或者拓展组件的element接口。它通过传入 props 来生成 element,不涉及 state 状态。 其创建形式如下:

function Tab (props) {
  return <div>{props.value}</div>
}

创建无状态组件减少了代码量,它只有一个 render 方法,并且没有组件的生命周期方法,在某开发中我们可以将一些功能简单单一的组件使用无状态组件来实现。

使用 React.createClass 和 React.Component 定义组件

Component 和 ReactClass 关系

除了无状态组件,我们最常用的就是这两种方式创建 component ,一般开发中我们会选择其中一种方式来创建组件,不建议混用。以下这张图我们可以简单了解到这两者之间的关系:

image

上图中 Constructor 其实是 React.createClass 方法返回的组件类,我们暂且称为 ReactClass ,它其实继承了 Component 类,在它的基础上增加了一些扩展。

Component 和 ReactClass区别

这两者都是创建 react 组件的方式,但是两者还是有一定的区别,主要在一下四个地方:

1. 语法层面
createClass 是一个工厂函数,通过传入配置对象的方式来生成 react 组件类,它的创建方式如下:

React.createClass({
  render(){
  ...
  }
})

Component 本身就是一个组件类,我们通过继承它来新建一个的组件对象。以下就是使用了 es6 来创建

class Tab extends React.Component {  
  constructor(props) {
    super(props);
  }
  render() {
  ...
  }
}

由于 React.createClass 返回的其实是一个组件的类,所以其实我们可以这样写

var a = React.createClass({})
a.prototype = { ... } 来增加方法,但是这只是一个方法,并不推荐使用。

2. 默认属性
react 最常用的两个属性propsstate在这两种声明中都存在不同

createClass 通过getDefaultPropsgetInitialState来进行propsstate的初始化

React.createClass({
  getDefaultProps() {
    return {

    };
  },
  getInitialState () {
    return {

    };
  }
})

Component 通过初始化其属性即可声明初始化状态

class Tab extends React.Component {
  static defaultProps = {
    initialSelectedIndex: 0,
    onChange: () => {},
  };

  state = {selectedIndex: 0};
 }

为何在这两者中定义会不一致。 其实 defaultProps 就是 react 组件的静态方法, 我们也可以在 createClass 返回的 组件类上增加它。只是在使用createClass生成组件类的时候,会调用getDefaultProps方法。源码如下:

var ReactClass = {
  createClass function(spec) {
    var Constructor = function(props, ...) {
      ...
      var initialState = this.getInitialState ? this.getInitialState() : null;
      this.state = initialState;
    };
    ...
    if (Constructor.getDefaultProps) {
      Constructor.defaultProps = Constructor.getDefaultProps();
    }
    return Constructor
  }
}

3. this上下文
createClass通过bindAutoBindMethod方法将其在 component element 中的方法绑定到 component 对象上。而 Component 则没有做这个处理,需要我们手动去绑定,可以使用bind来实现。区别如下:

//createClass
React.createClass({  
  handleClick() {
    console.log(this);
  },
  render() {
    return (
      <div onClick={this.handleClick}></div>
    );
  }
});

//Component
class Tab extends React.Component {  
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    console.log(this);
  }
  render() {
    return (
      <div onClick={this.handleClick}></div>
    );
  }
}

建议在 constructor 中绑定,避免在 render 使用 bind 绑定,你也可以使用箭头函数

4. Mixins特性
React.createClass 在创建组件时通过 mixSpecIntoComponent 添加 mixins 的属性,我们可以把混合的类的集合以数组的形式赋给 mixins 。但是在 Component 中则去掉了这个属性。mixins特性放到下一篇再讲。

目录