先给出结论,这其实是殊途同归的两种方式。过去我们一般都会使用 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/

转载于:https://www.cnblogs.com/xiaozhumaopao/p/8311307.html

转载 React.createClass 对决 extends React.Component相关推荐

  1. React.createClass和extends Component的区别

    语法区别 propType 和 getDefaultProps 状态的区别 this区别 Mixins 语法区别 React.createClass import React from 'react' ...

  2. [react] React.createClass和extends Component的区别有哪些?

    [react] React.createClass和extends Component的区别有哪些? 1.语法 React.createClass和extends采用函数构造 extends Comp ...

  3. 如何在React JS组件和React JS App中添加CSS样式?

    In this tutorial, we will only work with CSS styles. Please ensure you have basic knowledge of HTML, ...

  4. React 全家桶(react脚手架 redux react-redux react-router-dom ui库 reactHook)含 自定义hook的方法及使用

    文章目录 React 入门 React 简介 React 为何物 为何学习 React React 初体验 来一发 Hello React 创建虚拟 DOM 的两种方式:JS 和 JSX 虚拟 DOM ...

  5. React学习笔记一(React入门+JSX+脚手架)

    文章目录 1. React介绍和特点 1.1 React是什么 1.2 React的特点 2. React的开发依赖 2.1 React的三个依赖 2.2 Babel和React的关系 2.3 Rea ...

  6. php继承exten,es6,extends_react中通过extend继承,父组件为什么能访问子组件的属性,es6,extends,react.js - phpStudy...

    react中通过extend继承,父组件为什么能访问子组件的属性 代码如下,在父类的componentWillMount方法中输出 this,打印的却是子类 item 通过webpack的编译后文件中 ...

  7. React router 的 Route 中 component 和 render 属性理解

    React router 的 Route 中 component 和 render 属性理解 Route 标签的三个互斥属性 render.component.children Route 就是用来匹 ...

  8. React.createClass()方法

    react组件 -- React.createClass()方法 1.React.createClass()方法用于生成一个组件类 2.所有组件类都必须有自己的render方法,用于输出组件 3.假如 ...

  9. 04.React事件 方法、 React定义方法的几种方式 获取数据 改变数据 执行方法传值...

    2019独角兽企业重金招聘Python工程师标准>>> 一.基本用法 在以类继承的方式定义的组件中,为了能方便地调用当前组件的其他成员方法或属性(如:this.state),通常需要 ...

最新文章

  1. 每日一皮:据说PM就是这样忍受你的!
  2. Redis-序列化和存储模式
  3. Oracle 数据库修改配置文件sga_target参数的值,sga_target值太小导致数据库服务起不来问题解决,调大sga_target参数方法
  4. ORACLE 动态SQL中的多个单引号
  5. 在计算机中 鼠标器属于,在计算机中,鼠标器属于()。
  6. 《科学+ 预见人工智能》——物理学家的管理方式
  7. python采用面向对象编程模式吗_在python中,面向对象还有用吗?
  8. iOS 推送通知及推送扩展
  9. mongo php 自增,PHP7下MongoDB自增或自减一个字段的值
  10. crossorigin注解添加了解决不了跨域问题_springboot 处理跨域的2种方式
  11. Spring Boot——2分钟构建spring web mvc REST风格HelloWorld
  12. 标识符的作用域与可见性
  13. xpraid安装_XP系统怎么安装raid驱动|XP系统安装raid驱动的方法
  14. PMP考试知识总结【精华--持续更新】
  15. 富士通Fujitsu DPK9500GA Pro 打印机驱动
  16. ArcGIS Pro与ArcGis区别
  17. win10解除usb禁用_Win10系统禁用usb存储设备的设置方法
  18. 数学建模与数据分析中的主成分分析
  19. 服务器系统浏览器打不开,电脑浏览器打不开解决方法
  20. MVVM和MCV模式

热门文章

  1. Valve CEO:脑机接口技术可加强游戏体验远超“肉体外设“
  2. seaborn系列 (17) | 回归模型图lmplot()
  3. [CES 2018] 联想公布全球首款Daydream一体机,第二季度或将发售
  4. 一些有意思的VR设备介绍
  5. java 查找一行_Java培训之工具类通用的查询一行多列,非实体
  6. 数牍科技完成超3亿元A轮融资,隐私工程守护数据全生命周期流通协作
  7. 清华硕士在家造了一辆车,从设计到加工一个人完成,轻松穿沙漠爬岩石,还人人可拆装...
  8. 一块CPU就能运行超逼真水流特效!胡渊鸣的算法被这样实现,本人看了都说好...
  9. Oracle12c 从入门到精通(第二版) 闫红岩 金松河 编著
  10. github push时候报错解决方法