文档章节

结合 ES6+ 开发 React 组件

OSC编辑部
 OSC编辑部
发布于 2015/07/09 17:09
字数 1123
阅读 315
收藏 4

这是 Steven Luscher 写的一篇关于 React 的文章,Steven Luscher 擅长使用 React 和 GraphQL 构建应用。

原文地址:http://babeljs.io/blog/2015/06/07/react-on-es6-plus/ 

当重新设计 Instagram Web 的时候,使用了一些 ES6+ 的特性来编写 React 组件。在这里简要的说一下这些语言新特性对 React 应用的开发有什么影响,这些 ES6+ 特性使得 React 开发更简单更有趣。

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

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() { … }
}

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

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

// 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
  }
}

属性初始化程序

在 ES6+ 类的世界里,prop types 和 defaults live 在类自身作为静态属性。这些,在组件的初始化状态也是一样的,可以使用 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 指向 construction 的类实例,所以初始化状态可以依赖于 this.props。值得关注的是,我们不再定义 prop 默认值和使用 getter 函数初始化状态对象。

Arrow 函数

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

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

// 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 和属性初始化程序  – 可以选择绑定组件实例:

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

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

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

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

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

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

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

解构 & 传播属性

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

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 属性: 

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

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

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

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

© 著作权归作者所有

共有 人打赏支持
OSC编辑部

OSC编辑部

粉丝 265
博文 37
码字总数 35979
作品 0
深圳
私信 提问
结合 ES6+ 开发 React 组件

这是 Steven Luscher 写的一篇关于 React 的文章,Steven Luscher 擅长使用 React 和 GraphQL 构建应用。 原文地址:http://babeljs.io/blog/2015/06/07/react-on-es6-plus/ 当重新设计 Inst...

OSC编辑部
2015/07/09
31.1K
2
谈谈React

React无限好,只是我矫情 前置知识点: ES6的class ES6的模板字符串 ES6的模块Modules 本文带有强烈的个人观点,虽然我真的很喜欢React,React真的好用! 但是喜欢不等于无脑,学习其中的精髓才是重...

L3ve
2016/09/14
108
1
React+webpack+es6的环境配置及demo改写

写于 2016.05.14 前言 项目地址:jrainlau/react-es6 最近在家闲得无聊,所以打算折腾一下react。在此之前,我是一个vue的重度使用用户,但是看到react确实非常火爆,所以也就趁此机会去了解...

Jrain
2018/12/10
0
0
iOS开发者React Native学习路线

http://blog.talisk.cn/blog/2016/08/13/RN-Learning-path-for-iOS-developer/ 既然是写给iOS开发者的,那么我默认你已经掌握iOS原生应用开发的基本知识,所以对iOS原生开发的相关内容不做解...

卡奇匠
2016/12/13
18
0
react native的一些基本概念

理解react native 一般做纯客户端Native开发的人,如果只是听说过react native,没有仔细了解的话,会本能的认为 react native是一个东西,是某种语言或某个开发模式。那咱们先从感性上认识r...

totogo2010
2016/06/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何高效地遍历 MongoDB 超大集合?

GitHub 仓库:Fundebug/loop-mongodb-big-collection 本文使用的编程语言是 Node.js,连接 MongoDB 的模块用的是mongoose。但是,本文介绍的方法适用于其他编程语言及其对应的 MongoDB 模块。...

Fundebug
2分钟前
0
0
把自己的代码发布到CocoaPods上

由于多个项目用到同一个功能,所以想把该功能模块化 主要参考了这篇文章:自己的库上传到pod详细步骤 不过还是遇到很多坑。 1,先在GitHub上创建一个仓库。比如我创建了一个PPodTest 2, 克隆...

山里来的
10分钟前
0
0
[activiti6]在springboot增加restful api服务

<activiti.version>6.0.0</activiti.version>... <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-rest</artifactId> ......

Danni3
16分钟前
0
0
毕业季,我的Linux求职之路

毕业季,我的Linux求职之路 秋招终于告一段落了,本硕的七年求学之路也快画上了句号。回首求职的这一段日子,痛苦并快乐着。感谢所有陪伴着我走过这一段路程的同学,所有的辛酸都值得铭记。求...

linuxCool
19分钟前
0
0
PHP教程中验证正整数is_int($value+0),为什么要这样?

最近学习PHP应用,其中有一段是要验证变量是否为正整数,除了is_numeric($value)外,还要加上is_int($value+0)且($value+0) > 0,为什么还要 +0呢?直接验证$value不行吗? ,只要 is_int($...

dragon_tech
43分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部