先给出结论,这其实是殊途同归的两种方式。过去我们一般都会使用 React.createClass 方法来创建组件,但基于 ES6 的小小语法糖,我们还可以通过 extends React.Component 来创建组件。

这两种创建方式之间的差别很小,但只有了解这些颇有趣味的区别之后,我们才能做出最适合自己的选择。

语法区别

首先,让我们通过两个代码片段和相应的解释来看看到底有哪些语法区别。

React.createClass

我们先把新创建的 class 赋给一个常量,并添上 render 函数以完成最基本的组件定义。

import React from 'react';

const Contacts = React.createClass({
render() {
return (
<div></div>
);
}
}); export default Contacts;

React.Component

接下来把上面 React.createClass 定义的部分转换成 ES6 代码。

import React from 'react';

class Contacts extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div></div>
);
}
} export default Contacts;

从 JavaScript 语言层面来看,我们已经在使用 ES6 中的类了,通常这些 ES6 代码需要使用类似 Babel 的工具转换为 ES5 代码之后才能在浏览器中正常执行。这里我们引入了一个叫 constructor 的东西,因为我们需要在这里调用 super() 函数来为 React.Component 传递属性。

在这次代码转换中,我们通过继承 React.Component 代替直接调用 React.createClass 的方式,创建了一个叫做“Contacts”的类,使得这段代码中 JavaScript 的味道变得更浓郁了。在整个语法转换的过程中,这一步具有革命性的意义。

propType 和 getDefaultProps

这是个关乎如何使用、声明默认属性和类型,以及如何设置给类初始化状态的重要变化。

React.createClass

在调用 React.createClass 时,我们添加了一个叫做 propTypes 的对象,只要给它的属性进行赋值就能声明对应属性的类型。 getDefaultProps 这个函数返回了一个对象,这个对象的所有属性将会作为组件的初始化属性。

import React from 'react';

const Contacts = React.createClass({
propTypes: { },
getDefaultProps() {
return { };
},
render() {
return (
<div></div>
);
}
}); export default Contacts;

React.Component

转换语法之后,我们通过给 Contacts 类添加一个名为 propTypes 属性的方式来达到和上面同样的效果。我认为这种方式比之前更加干净简洁了。

而 getDefaultProps 函数也变成了一个名为 defaultProps 的属性,注意它仅仅是一个对象而不是“get”函数。我更喜欢这种语法,因为它跳出了 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.Component

转换以后 getInitialState 函数被抛弃了,我们在 constructor 中像创建初始化属性一样声明了所有状态,我认为这样更加像 JavaScript 并且更少地驱动了“API”(译注:这里“更少地驱动了 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 时 React 会自动帮我们处理函数中的 this 指针,但使用 ES6 的话 this 将会失效。

React.createClass

注意,我们在 onClick 属性上绑定了 this.handleClick。当点击事件被触发时,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>
);
}

我们可以像下面这样在行内代码中绑定正确的执行上下文:

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;

除此之外,我们也可以在 constructor 中来改变 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 mixins 的特性将不能被使用了。

React.createClass

使用 React.createClass 的话,我们可以在创建组件时添加一个叫做 mixins 的属性,并将可供混合的类的集合以数组的形式赋给 mixins

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

但在 ES6 中,mixins 特性不被支持。

建议

Facebook 官方的建议是,等到 ES6 中的类对所有特性有完整支持的时候弃用 React.createClass。但现在,凭感觉去使用吧,它们本质上还是殊途同归的两种方式——说到底它俩不都是类嘛!

原文地址:https://www.peachis.me/react-createclass-versus-extends-react-component/

转载 React.createClass 对决 extends React.Component的更多相关文章

  1. React.createClass和extends Component的区别

    React.createClass和extends Component的区别主要在于: 语法区别 propType 和 getDefaultProps 状态的区别 this区别 Mixins 语法区别 ...

  2. React.createClass 、React.createElement、Component

    react里面有几个需要区别开的函数 React.createClass .React.createElement.Component 首选看一下在浏览器的下面写法: <div id=" ...

  3. 【React Native开发】React Native移植原生Android项目(4)

    ),React Native技术交流4群(458982758),请不要反复加群!欢迎各位大牛,React Native技术爱好者加入交流!同一时候博客左側欢迎微信扫描关注订阅号,移动技术干货,精彩文章 ...

  4. React-Native(三):React Native是基于React设计的

    React Native是基于React js设计的. 参考:<React 入门实例教程> React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript ...

  5. react基础学习和react服务端渲染框架next.js踩坑

    说明 React作为Facebook 内部开发 Instagram 的项目中,是一个用来构建用户界面的优秀 JS 库,于 2013 年 5 月开源.作为前端的三大框架之一,React的应用可以说是非常 ...

  6. React(7) --react父子组件传参

    react父子组件传参 父级向子级传参:在父组件中,我们引入子组件,通过给子组件添加属性,来起到传参的作用,子组件可以通过props获取父组件传过来的参数. 在父组件中: import React f ...

  7. React.createClass vs. ES6 Class Components

    1 1 1 https://www.fullstackreact.com/articles/react-create-class-vs-es6-class-components/ React.crea ...

  8. [React Native] Using the WebView component

    We can access web pages in our React Native application using the WebView component. We will connect ...

  9. [React Native] Using the Image component and reusable styles

    Let's take a look at the basics of using React Native's Image component, as well as adding some reus ...

随机推荐

  1. jsp标签之jsp:setProperty用法

    参考:http://blog.csdn.net/wanghaishanren/article/details/2047400

  2. [BZOJ1269]文本编辑器editor

    Problem 有n个操作 Solution splay模板题,用splay维护下标. Notice 需要把l的前一个位置旋转到根,r的后一个位置旋转到根的右节点.所以特别要注意0的大坑. Code ...

  3. 《Python》hashlib模块、configparser模块、logging模块

    一.hashlib模块 Python的hashlib模块中提供了常见的摘要算法,如md5,sha1等等. 摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的字符串(通 ...

  4. bootstrap table 分页显示问题

    1.bootstrap-table客户端分页 客户端分页的数据源可以是后台服务器端传递过来(一次性获取,即获取所有你需要的数据),点击页码不再请求后台,利用页面缓存分页;cache : true, / ...

  5. FFT理解

     *连续时间-周期性信号频谱 clc;clear;close all N = input('N= '); T = 0.05; n = 1:N; %原始数据输入 D = 2*pi/(N*T); %计算分 ...

  6. 监控中的TP50

    TP指标: TP50:指在一个时间段内(如5分钟),统计该方法每次调用所消耗的时间,并将这些时间按从小到大的顺序进行排序,取第50%的那个值作为TP50 值:配置此监控指标对应的报警阀值后,需要保证在 ...

  7. python 列表和元组

    一,基本的列表操作 1.该表列表,元素赋值 示例: >>>x = [1,1,1] >>>x[1] = 2 >>>x [1,2,1] 2.删除元素 ...

  8. MVC中如何避免POST请求中出现的重复提交

    使用惯了Asp.Net的服务器控件了, 突然转到MVC框架上来遇到这么个问题. 比如说网速慢的时候, 用户频繁的点击提交按钮, 或者是按F5刷新页面等等.解决方法很简单. 解决方案 1. 在页面生成时 ...

  9. shelly - HYMN TO INTELLECTUAL BEAUTY

    HYMN TO INTELLECTUAL BEAUTY III No voice from some sublimer world hath ever ⁠To sage or poet these r ...

  10. [学习] SpringMVC/JavaEE/JavaSE

    浅谈@RequestMapping @ResponseBody 和 @RequestBody 注解的用法与区别 几个Map集合的区别 Java多线程