在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」的组件是通过继承(extends
)React.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); }, 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); } 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); } 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); } 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(); }, render() { return ( <div onClick={this.handleClick}></div> ); } }); export default Contacts;
|
React.Component
不支持
建议
Facebook建议使用ES6 classes而不是React.createClass
,因为将来会被废除。而现在,使用最适合你项目的语法吧,他们只是不同的语意做着同样的事情, they’re both classes!