React.createClass-versus-extends-React.Component(译)

  • 白小霁
  • 26 Minutes
  • June 13, 2017

在React的官网中,告诉我们实现一个组件的用法是使用React.createClass,而在实际的项目过程中,我们往往使用的extends React.Component的方法,而这样两种使用有什么区别吗?所以查找到了这样的一篇文章。想看原文,点这里原文地址

这是实现组件的两种方式。传统情况下,React提供了React.createClass方法去构建一个组件,但由于一个语法糖(extends)方法的发布,并更新到容许使用ES6模块化的方式,即extends React.Component的方式,就是继承React.Component类代替createClass

这两种方式的不同点其实很微小,但期间有一些有趣的不同值得去探索一下,了解过后你就能在项目中做出最佳选择方式的决定。

语法的不同

首先,一起通过看两个例子和注释来发现两者的不同。

React.createClass

这里我们使用const来标记React class,并且使用最为重要的render方法构建一个典型、基础的React组件。

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
const Contacts = React.createClass({
render() {
return (
<div></div>
);
}
});
export default Contacts;

React.Component

上面我们采取的React.createClass定义的方法,现在我们使用 ES6 class 的语法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div></div>
);
}
}
export default Contacts;

从JavaScript的角度看,我们现在使用的是ES6 classes的语法,很明显我们需要使像Babel这样的工具,将ES6语法 编译为 ES5语法,从而能在其他的浏览器上跑起来。以此,我们需要了解constructor,就是需要调用super()方法,将props传递给React.Component

对于React的改变,现在我们创建一个名为「Contacts」的组件是通过继承(extendsReact.Component的方式替代了调用React.createClass,从让使用这使用更多的JavaScript而不是React的API。这是一个重要的变化,让我们注意要换掉原来的语法。

propTypes and getDefaultProps

在我们声明default props,设置他们类型和初始值的时候有着重要的改变。

React.createClass

React.createClass中,propType属性是一个可以申明每一个prop值类型的对象。而getDefaultProps属性是一个函数return一个创建初始化props值的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';
const Contacts = React.createClass({
propTypes: {
},
getDefaultProps() {
return {
};
},
render() {
return (
<div></div>
);
}
});
export default Contacts;

React.Component

这里propType则是作为Contacts类的一个属性,而不是createClass方法的一部分属性。

这时getDefaultProps在这个class中作为对象的属性被名为defaultProps,不再是一个「get」的函数,仅仅是一个对象。我喜欢这样的语法,他避免了过于React模板化,现在只有JavaScript。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div></div>
);
}
}
Contacts.propTypes = {
};
Contacts.defaultProps = {
};
export default Contacts;

State differences

State是一个有趣的变化,现在我们使用constructors 去是实现初始化的states。

React.createClass

我们使用只返回一个初始化states对象的getInitialState方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
const Contacts = React.createClass({
getInitialState () {
return {
};
},
render() {
return (
<div></div>
);
}
});
export default Contacts;

React.Component

这里getInitialState被废弃了,我们声明所有的初始的states在constructor中,这让我使用的更像JavaScript一样而不是要API驱动的样子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div></div>
);
}
}
export default Contacts;

“this” differences

使用React.createClass会自动的绑定this的值,而使用ES6 的时候就不会。

React.createClass

注意这里的onClick绑定了this.handleClick。当整个方法被调用的时候,React将这个方法(handleClick)放置在正确的执行上下文中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react';
const Contacts = React.createClass({
handleClick() {
console.log(this); // React Component instance
},
render() {
return (
<div onClick={this.handleClick}></div>
);
}
});
export default Contacts;

React.Component

使用ES6 classes下this有点不一样,所有作为了的属性不会自己将this绑定到React 类的实例上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
}
handleClick() {
console.log(this); // null
}
render() {
return (
<div onClick={this.handleClick}></div>
);
}
}
export default Contacts;

这里有几个方法让我们可以将this绑定到正确的上下文,下面我们使用行内绑定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
}
handleClick() {
console.log(this); // React Component instance
}
render() {
return (
<div onClick={this.handleClick.bind(this)}></div>
);
}
}
export default Contacts;

或者我们可以将this.handleClick的写在constructor中避免过多的行内重复。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this); // React Component instance
}
render() {
return (
<div onClick={this.handleClick}></div>
);
}
}
export default Contacts;

Mixins

在使用ES6 的语法使用React的mixin是不支持的。

React.createClass

我们给组件增加mixins使用数组类型的mixins属性,这些在被组件继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from 'react';
var SomeMixin = {
doSomething() {
}
};
const Contacts = React.createClass({
mixins: [SomeMixin],
handleClick() {
this.doSomething(); // use mixin
},
render() {
return (
<div onClick={this.handleClick}></div>
);
}
});
export default Contacts;

React.Component

不支持

建议

Facebook建议使用ES6 classes而不是React.createClass,因为将来会被废除。而现在,使用最适合你项目的语法吧,他们只是不同的语意做着同样的事情, they’re both classes!