转载 React.createClass 对决 extends React.Component
先给出结论,这其实是殊途同归的两种方式。过去我们一般都会使用 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的更多相关文章
- React.createClass和extends Component的区别
React.createClass和extends Component的区别主要在于: 语法区别 propType 和 getDefaultProps 状态的区别 this区别 Mixins 语法区别 ...
- React.createClass 、React.createElement、Component
react里面有几个需要区别开的函数 React.createClass .React.createElement.Component 首选看一下在浏览器的下面写法: <div id=" ...
- 【React Native开发】React Native移植原生Android项目(4)
),React Native技术交流4群(458982758),请不要反复加群!欢迎各位大牛,React Native技术爱好者加入交流!同一时候博客左側欢迎微信扫描关注订阅号,移动技术干货,精彩文章 ...
- React-Native(三):React Native是基于React设计的
React Native是基于React js设计的. 参考:<React 入门实例教程> React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript ...
- react基础学习和react服务端渲染框架next.js踩坑
说明 React作为Facebook 内部开发 Instagram 的项目中,是一个用来构建用户界面的优秀 JS 库,于 2013 年 5 月开源.作为前端的三大框架之一,React的应用可以说是非常 ...
- React(7) --react父子组件传参
react父子组件传参 父级向子级传参:在父组件中,我们引入子组件,通过给子组件添加属性,来起到传参的作用,子组件可以通过props获取父组件传过来的参数. 在父组件中: import React f ...
- React.createClass vs. ES6 Class Components
1 1 1 https://www.fullstackreact.com/articles/react-create-class-vs-es6-class-components/ React.crea ...
- [React Native] Using the WebView component
We can access web pages in our React Native application using the WebView component. We will connect ...
- [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 ...
随机推荐
- 读书笔记 C# 接口中的索引器之浅析
在C#中,可以在类.结构或接口中用this关键字声明索引器,在索引器内部用get或set访问器访问类中集合的某项值.因此可以将索引器看作是类的属性一样去定义.索引器常用定义格式如下: public i ...
- unordered_map/unordered_set & unordered_multimap/unordered_multiset非关联容器
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- vue.set动态新增对象属性,触发dom渲染
当我们给一个props或者data中被观测的对象添加一个新的属性的时候,不能直接添加,必须使用Vue.set方法 /** * ==== 选择产品 ==== * 因为vue实现双向数据绑定的机制是数据劫 ...
- opencv3.0+vs2013安装记录
为了能够更好的学习图像,我觉得opencv是一个必不可少的库,因此在以后的研究上使用opencv作为研究工具,与大家共同进步. 话归正题:先搭建opencv的环境. 1.下载安装包3.0 a,官网打开 ...
- 2.12 C++ explicit关键字详解
参考:http://www.cnblogs.com/ymy124/p/3632634.html 总结: 带参数的构造函数中有两种比较常见的构造函数:拷贝构造函数和转型构造函数. 转型构造函数只有一个参 ...
- Unicode与中文转换工具类方法(转)
/* * 中文转unicode编码 */ public static String gbEncoding(final String gbString) { char[] utfBytes = gbSt ...
- python中变量命名的基本规则,标识符和关键字
变量的命名 目标 标识符和关键字 变量的命名规则 0.1 标识符和关键字 1.1 标识符 标示符就是程序员定义的 变量名.函数名 名字 需要有 见名知义 的效果,见下图:  标示符可以由 字母.下划 ...
- YLZ开发外网前端
YLZ外网前端使用的是boottstrap和layer和validform等插件 表格是用boottstrap的tablle加上框架人员开发的ajaxpageresponse进行协调开发 弹窗使用的l ...
- L251
Beer before wine, or wine before beer; whatever the order, you’ll feel queer. That, at least, is the ...
- python day14--内置函数二
主要内容: 1.lamda匿名函数 2.sorted() 3.filter() 4.map() 5.递归函数 一.Lamda匿名函数 语法:lamda:参数:返回值 # 计算n的n次⽅方 def fu ...