React.createClass 对比 extends React.Component
React提供了React.createClass方法来创建组件类并且发布了一个语法糖更新,通过扩展React.component类而不是调用createclass的方法,更好使用ES6模块
- 1.语法区别
- 2.propTypes and getDefaultProps
- 3.State区别
- 4.“this”的区别
- 5.Mixins
- 6.建议
这些差异在各个地方都很微妙,有许多值得探讨的差异,了解这些差异,帮助你做出最适合决策。
语法区别
首先,我们通过查看两个代码示例,对它们进行注释来研究语法差异。
React.createClass
在这里我们指定React类的变量Contacts , 运用render函数来完成一个典型的基础组件定义。
import React from 'react'; const Contacts = React.createClass({ render() { return ( <div></div> ); } }); export default Contacts;
React.Component
参考上面的代码,用ES6 的 class 实现一个相同的组件。
import React from 'react'; class Contacts extends React.Component { constructor(props) { super(props); } render() { return ( <div></div> ); } } export default Contacts;
从JavaScript的角度来看,我们现在使用的是ES6类,通常这会与Babel之类的一起使用,将ES6编译为ES5在浏览器中工作。 通过上面的写法,用到了constructor,需要调用super()将props传递给React.Component。
对于React更改,我们从React.Component扩展得到一个名为“Contacts”的类, 而不是直接调用React.createClass,减少了的React模板的使用,更多的用到了JavaScript。 这是一个重要的改变,要注意这个语法变化带来的进一步变化。
propTypes and getDefaultProps
让我们来看看, 如何使用和声明default props,以及它们的类型和设置初始状态的重要变化。
React.createClass
在React.createClass中,propTypes属性是一个Object,我们可以在其中声明每个prop的类型。 getDefaultProps属性是一个返回Object来创建初始props的函数。
import React from 'react'; const Contacts = React.createClass({ propTypes: { }, getDefaultProps() { return { }; }, render() { return ( <div></div> ); } }); export default Contacts;
React.Component
这将propTypes用作实际Contacts类的属性,而不是作为createClass定义Object的的属性。 我认为创建类属性是更好的语法,自己定义类属性,比用react 的 api 更加清晰。
getDefaultProps现在已经变成了名为defaultProps的Object类属性,它不再是“get”函数,它只是一个Object。 我喜欢这种语法,因为它避免了更多的React模板,只是普通的JavaScript。
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区别
状态的变化很有趣,我们使用构造函数实现初始状态更改。
React.createClass
这里有一个getInitialState函数,它只是返回一个初始状态的对象。
import React from 'react'; const Contacts = React.createClass({ getInitialState () { return { }; }, render() { return ( <div></div> ); } }); export default Contacts;
React.conponent
getInitialState函数已经废弃,我们将所有状态声明为构造函数中的一个简单的初始化属性,这更像JavaScript,更少的“API”驱动。
import React from 'react'; class Contacts extends React.Component { constructor(props) { super(props); this.state = { }; } render() { return ( <div></div> ); } } export default Contacts;
“this”的区别
使用React.createClass会自动绑定this的值到组件上,但使用ES6类时不会自动绑定。
React.createClass
带有this.handleClick绑定的onClick声明。 当这个方法被调用时,React会将正确的执行上下文应用于handleClick。
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类,类的属性不会自动绑定到React类实例。
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;
有几种方法可以绑定正确的上下文,以下是如何绑定内联:
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的上下文以避免内联重复,用这种方法避免修改JSX,是更好的方法:
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组件时,不再支持React mixins。
React.createClass
使用React.createClass,我们可以使用mixins属性将mixin添加到组件,该属性需要一个可用的mixin数组。 然后这些扩展组件类。
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确实建议将来彻底删除React.createClass以支持ES6类 。 现在,它们都只是语法不同的语义,它们做同样的事情 - 它们都是类!