在这里简要的说一下这些语言新特性对 React 应用的开发有什么影响,这些 ES6+ 特性使得 React 开发更简单更有趣。

迄今为止,最能体现我们使用 ES6+ 来编写 React 组件的就是我们选择使用类定义语法。替代了使用 React.createClass 方法来定义一个组件,我们可以定义一个 bonafide ES6 类来扩展 React.Component:

1
2
3
4
5
class Photo extends React.Component {
  render() {
    return <img alt={this.props.caption} src={this.props.src} />;
  }
}

现在,你就会发现一个微妙的差异 —— 当使用定义类的时候语法更简洁:

1
2
3
4
5
// The ES5 way
var Photo = React.createClass({
  handleDoubleTap: function(e) { … },
  render: function() { … },
});
1
2
3
4
5
// The ES6+ way
class Photo extends React.Component {
  handleDoubleTap(e) { … }
  render() { … }
}

值得关注的是,我们去掉了两个括号和一个分号,每个方法声明我们省略了一个冒号,一个关键字和一个分号。

当使用新的类定义时,所有的生命周期方法至少有一个是符合你期望的。类的 constructor 现在假设 role 之前是通过 componentWillMount 填充的:

1
2
3
4
// The ES5 way
var EmbedModal = React.createClass({
  componentWillMount: function() { … },
});
1
2
3
4
5
6
7
// The ES6+ way
class EmbedModal extends React.Component {
  constructor(props) {
    super(props);
    // Operations usually carried out in componentWillMount go here
  }
}

属性初始化程序

在 ES6+ 类的世界里,prop types 和 defaults live 在类自身作为静态属性。这些,在组件的初始化状态也是一样的,可以使用 ES7 property initializers 定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// The ES5 way
var Video = React.createClass({
  getDefaultProps: function() {
    return {
      autoPlay: false,
      maxLoops: 10,
    };
  },
  getInitialState: function() {
    return {
      loopsRemaining: this.props.maxLoops,
    };
  },
  propTypes: {
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired,
  },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// The ES6+ way
class Video extends React.Component {
  static defaultProps = {
    autoPlay: false,
    maxLoops: 10,
  }
  static propTypes = {
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired,
  }
  state = {
    loopsRemaining: this.props.maxLoops,
  }
}

ES7 属性初始化程序操作内部类的 constructor,this 指向 construction 的类实例,所以初始化状态可以依赖于 this.props。值得关注的是,我们不再定义 prop 默认值和使用 getter 函数初始化状态对象。

Arrow 函数

React.createClass 方法用来在你的组件实例方法中执行一些额外的绑定工作,为了确保 this 关键字会指向组件实例:

1
2
3
4
5
6
7
// Autobinding, brought to you by React.createClass
var PostInfo = React.createClass({
  handleOptionsButtonClick: function(e) {
    // Here, 'this' refers to the component instance.
    this.setState({showOptionsModal: true});
  },
});

自从我们不参与 React.createClass 方法,而是使用 ES6+ 类语法定义组件,看似需要手动绑定实例方法:

1
2
3
4
5
6
7
8
9
10
11
12
// Manually bind, wherever you need to
class PostInfo extends React.Component {
  constructor(props) {
    super(props);
    // Manually bind this method to the component instance...
    this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this);
  }
  handleOptionsButtonClick(e) {
    // ...to ensure that 'this' refers to the component instance here.
    this.setState({showOptionsModal: true});
  }
}

幸运的是,通过绑定两个 ES6+ 特性 – arrow functions 和属性初始化程序  – 可以选择绑定组件实例:

1
2
3
4
5
class PostInfo extends React.Component {
  handleOptionsButtonClick = (e) => {
    this.setState({showOptionsModal: true});
  }
}

ES6 的 arrow 函数体分享相同的词  this,用这来围绕他们的代码,这些可以达到我们预期的结果,也是 ES7 属性初始化程序在域内的方式。 Peek under the hood 来看看为什么能实现。

动态属性名称 & 模板字符串

其中一个对象常量增强是可以分配到一个派生属性名称。我们最初可能会像下面这样设置一些状态:

1
2
3
4
5
6
7
var Form = React.createClass({
  onChange: function(inputName, e) {
    var stateToSet = {};
    stateToSet[inputName + 'Value'] = e.target.value;
    this.setState(stateToSet);
  },
});

现在,我们有能力构造通过一个运行时 JavaScript 表达式确定属性名称的对象。这里,我们使用了一个模板字符串来确定哪个属性设置状态:

1
2
3
4
5
6
7
class Form extends React.Component {
  onChange(inputName, e) {
    this.setState({
      [`${inputName}Value`]: e.target.value,
    });
  }
}

解构 & 传播属性

通常在编写组件的时候,我们可能想把大部分父组件的 props 传递给子组件,但不是所有。结合 ES6+ 解构和 JSX 传播属性,这个不需要多余的部分就能实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class AutoloadingPostsGrid extends React.Component {
  render() {
    var {
      className,
      ...others,  // contains all properties of this.props except for className
    } = this.props;
    return (
      <div className={className}>
        <PostsGrid {...others} />
        <button onClick={this.handleLoadMoreClick}>Load more</button>
      </div>
    );
  }
}

我们可以结合 JSX 传播属性和常规属性,利用一个简单的优先原则实现 overrides 和 defaults。这个元素会要求 className “override” 甚至是在 this.props 存在 className 属性:

1
2
3
<div {...this.props} className="override">
   … 
</div>

这个元素常规来说需要 className “base” ,除非 this.props 有 className 属性覆盖:

1
2
3
<div className="base" {...this.props}>
   … 
</div>

希望大家能享受 ES6+ 语言特性给 React 开发带来的一些便利。

ES6+ 开发 React 组件的更多相关文章

  1. React组件开发入门

    React 组件开发入门 Introduction 本文组成: Ryan Clark文章Getting started with React的翻译. 博主的实践心得. React由Facebook的程 ...

  2. 编写React组件的最佳实践

    此文翻译自这里. 当我刚开始写React的时候,我看过很多写组件的方法.一百篇教程就有一百种写法.虽然React本身已经成熟了,但是如何使用它似乎还没有一个"正确"的方法.所以我( ...

  3. 从工程化角度讨论如何快速构建可靠React组件

    前言 React 的开发也已经有2年时间了,先从QQ的家校群,转成做互动直播,主要是花样直播这一块.切换过来的时候,业务非常繁忙,接手过来的业务比较凌乱,也没有任何组件复用可言. 为了提高开发效率,去 ...

  4. react开发中如何使用require.ensure加载es6风格的组件

    其实用的babel,在浏览器端就应该可以加载,之前少了个default: require.ensure([],(require) => { let A = require('./a.js').d ...

  5. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  6. react复习总结(1)--react组件开发基础

    这次是年后第一次发文章,也有很长一段时间没有写文章了.准备继续写.总结是必须的. 最近一直在业余时间学习和复习前端相关知识点,在一个公司呆久了,使用的技术不更新,未来真的没有什么前景,特别是我们这种以 ...

  7. sublime +react+es6开发环境

    Babel Sublime3才有的插件,支持ES6.JSX语法高亮. 菜单->View->Syntax->Open all with current extension as...- ...

  8. React 组件开发注意事项

    0.state的设定原则,如果render里用不到,则就不应该是一个state. 1.数组遍历时,用每一条数据的唯一标识作为key,尽量不要使用遍历的索引值作为key,如果它们从不重新排序,它们工作也 ...

  9. [webpack] 配置react+es6开发环境

    写在前面 每次开新项目都要重新安装需要的包,简单记录一下. 以下仅包含最简单的功能: 编译react 编译es6 打包src中入口文件index.js至dist webpack配置react+es6开 ...

随机推荐

  1. docker 技术

    利用docker打包一个sshd的服务 准备环境 安装docker     修改主机名与hosts解析     echo '10.0.0.11 docker01'     参考文档:https://m ...

  2. 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)

    传送门 题意简述:问有多少长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数,且其中至少有一个数是质数,答案对201704082017040820170408取模(n≤1e9, ...

  3. qhfl-6 购物车

    购物车中心 用户点击价格策略加入购物车,个人中心可以查看自己所有购物车中数据 在购物车中可以删除课程,还可以更新购物车中课程的价格策略 所以接口应该有四种请求方式, get,post,patch,de ...

  4. 20154305 齐帅 PC平台逆向破解

    Exp1 PC平台逆向破解 一.实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时 ...

  5. Mysql中比较常用的两种存储引擎和事务

    存储引擎:引擎(类似汽车上的发动机)决定了数据库的快慢,MySql中有20多个引擎,不同的存储引擎提供不同的存储机制.索引技巧.锁定水平.MYISAM存储引擎,INNODB存储引擎最出名.数据库的核心 ...

  6. bzoj3637(lct)

    又一次把lct写炸了,硬着头皮终于改对了 #include<iostream> #include<cstring> #include<cstdio> #includ ...

  7. Java变成思想总结

    Java容器 collection一个独立的元素序列,这些元素都服从一条或多条规则.list必须按照插入的顺序保存元素,set不能有重复元素,queue按照排队的顺序确定对象产生的顺序.map一组成对 ...

  8. 【Selenium专题】鼠标键盘事件

    引用包来自selenium-java-2.23.1.jar 调用以下代码时,需要引入actions类,以java为例: import org.openqa.selenium.interactions. ...

  9. Angular使用总结 --- 通过指令动态添加组件

    之前自己写的公共组件,都是会先引入,需要调起的时候再通过service控制公共组件状态.值.回调函数什么的.但是有一些场景不适合这种方式,还是动态添加组件更加好.通过写过的一个小组件来总结下. 创建组 ...

  10. Maven Optional & Exclusions 使用区别

    Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反. Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖 ...