react on es6+

转载 2016年08月28日 21:50:04

原文:React on ES6+
[译]在 React.js 中使用 ES6+

在今年对 Instagram Web 进行全新的设计的时候,我喜欢在写 React 组件的时候,用上一些 ES6+ 的新特性。请允许我列举这些能够改变你写 React 应用方式的新特性。比起以往,这些特性能够使你撸起码来更加容易、有趣!

类(Class)

使用 ES6+ 来编写 React 组件最明显的变化就是我们定义组件(类)的语法的方式。我们可以用定义一个继承了 React.Component 的ES6 类来代替原本使用 React.createClass 的来创建类的方式:

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

我们可以发现这种写法使得定义组件的方式变得更加简洁:

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

这样我们可以少写一对圆括号、一个分号、每个方法的冒号和 function 关键字。

所有生命周期方法都可以采用这种方式来定义。 但是 componentWillMount 还可以用 constructor 来代替:

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

属性初始化(property initializers)

在 ES6+ 类中,属性类型 prop type 和默认属性 default prop 可以通过类中的 static 来声明。同时,组件的初始状态( initial state )可以通过 ES7 的属性初始化(property initializers)来完成:

// 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,
  },
});
// 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 指向的是类的实例,所以初始状态( initial state )可以通过 this.prop (即传入的参数)来设定。

箭头函数(Arrow function)

React.createClass 方法在你的组件上做了一些额外的绑定工作,以确保在组件实实例的方法内部, this 指向的是组件实例自身。

// 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});
  },
});

由于我们使用 ES6+ 的语法定义类的时候没有采用 React.createClass 的方式,所以,这样看来我们不得不手动来绑定这些方法中 this 的指向:

// 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 )和属性初始化( property initializers )这两个特性使得把函数的 this 指向绑定为组件的实例变得非常的简单:

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

函数体内的 this 对象,绑定定义时所在的对象,而不是使用时所在的对象。而恰好属性初始化( property initializers )刚好在这个作用域内。

动态属性名 & 字符串模板

在 ES6+ 中对 对象字面量的扩展 使得我们可以在对象字面量中使用表达式来对属性命名。如果是在 ES5 中,我们也许只能这样做:

var Form = React.createClass({
  onChange: function(inputName, e) {
    var stateToSet = {};
    stateToSet[inputName + 'Value'] = e.target.value;
    this.setState(stateToSet);
  },
});

但是,在 ES6+ 中,我们不仅可以在对象字面量属性的定义中使用表达式,还有使用字符串模板 :

class Form extends React.Component {
  onChange(inputName, e) {
    this.setState({
      [`${inputName}Value`]: e.target.value,
    });
  }
}

析构 & 扩展运算符

我们在编写组件的过程中,经常遇到要从父组件要把自己的很多属性多传给子组件的情况。有了 ES6+ 的 析构 和 扩展运算符 特性,这变得非常的方便:

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>
    );
  }
}

我们可以把 扩展运算符 属性和普通的属性结合起来使用,这样使得我们可以利用优先级来使用属性的默认值和属性的覆盖。下面这个元素会获得一个 override 的类( class ),及时 this.props 中有传递 className 属性。

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

下面这种写法,可以给元素设定默认的 className:

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

最后

我希望你能够享受 ES6+ 的这些特性给你在编写 React.js 中带来的好处。感谢我的同事他们为这篇文章作出的贡献,还有,特别的感谢 Babel 团队,使得我们可以随意的使用这些特性。

webpack + Es6 + react

  • 2016年12月25日 21:30
  • 518KB
  • 下载

React+Webpack+ES6代码示例

  • 2017年11月27日 18:09
  • 11.81MB
  • 下载

【前端知识点】webpack 打包 + es6 + react入门(一)webpack打包

webpack 打包 + es6 + react入门本文主要针对webpack打包流程,注意事项,es6新特性变化,以及es6 开发react的入门教程: webpack打包流程 webpack注意事...

webpack+react+es6开发环境搭建

欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和...

webpack踩坑之路——构建基本的React+ES6项目

webpack是最近比较火的构建工具,搭配上同样比较火的ReacJS与ES6(ES2015)一定是现在很多潮流 programmer 的追求。 废话不多,下面就就看下如何从0搭起我们的构建工具。 安装...

使用 webpack + react + redux + es6 开发组件化前端项目

因为最近在工作中尝试了 webpack、react、redux、es6 技术栈,所以总结出了一套 boilerplate,以便下次做项目时可以快速开始,并进行持续优化。对应的项目地址:we...

使用 webpack + react + redux + es6 开发组件化前端项目

因为最近在工作中尝试了 webpack、react、redux、es6 技术栈,所以总结出了一套 boilerplate,以便下次做项目时可以快速开始,并进行持续优化。 项目结构规划 每个...

当React遇到了es6,让gulp来搭桥

前面介绍了如何搭建es6环境来开发,本章将一下React如何用es6来编写代码。 根据前面的基础我们加入react的jsx解析,首先回顾一下前面用到的gulp模块 之前我们安装了gulp,gu...

React-redux-webpack项目总结之用到的Es6基本语法

上个暑假在公司实习的一个app商城项目,十一月初才上线,也没来得及总结学到的东西,不过有关于前端这些日新月异的东西,说不定等我毕业又是一番新气象,不过就像我宇哥说的核心思想都不会发生太大变化,学会触类...
  • lsgqjh
  • lsgqjh
  • 2016年12月04日 15:53
  • 890

webpack踩坑之路——构建基本的React+ES6项目

webpack是最近比较火的构建工具,搭配上同样比较火的ReacJS与ES6(ES2015)一定是现在很多潮流 programmer 的追求。 废话不多,下面就就看下如何从0搭起我们的构建工具。 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:react on es6+
举报原因:
原因补充:

(最多只允许输入30个字)