天天看點

[譯]使用 ES6+ 寫 react

原文 : React on ES6+ :http://babeljs.io/blog/2015/06/07/react-on-es6-plus/ (英文不好,見諒哈)

Posted Jun 7, 2015 by Steven Luscher

This is a guest post from Steven Luscher. Steven works on Relay at Facebook – a JavaScript framework for building applications using React and GraphQL. Follow Steven on Instagram , GitHub , and Twitter .

While redesigning Instagram Web from the inside out this year, we enjoyed using a number of ES6+ features to write our React components. Allow me to highlight some of the ways that these new language features can change the way you write a React app, making it easier and more fun than ever.

雖然今年從内部重新設計Instagram Web,我們喜歡使用大量的ES6功能來編寫我們的React元件。

請允許我強調一些方法,這些新的語言功能可以改變你寫一個React應用程式的方式,使得它比以往任何時候更容易和更有趣。

Classes

By far the most outwardly visible change to how we write React components using ES6+ comes about when we choose to use the class definition syntax . Instead of using the React.createClass method to define a component, we can define a bonafide ES6 class that extends

React.Component

:

到目前為止,我們使用ES6編寫React元件的最明顯的變化是使用類來定義文法,

而不是使用React.createClass方法來定義元件,我們可以定義一個擴充

React.Component

的bonafide ES6類:

class Photo extends React.Component {
  render() {
    return <img alt={this.props.caption} src={this.props.src} />;
  }
}
           
Right away, you’ll notice a subtle difference – a more terse syntax is available to you when defining classes:

你會注意到一個微妙的差别 - 定義類時可以使用更簡潔的文法:

// The ES5 way
var Photo = React.createClass({
  handleDoubleTap: function(e) { … },
  render: function() { … },
});
           
// The ES6+ way
class Photo extends React.Component {
  handleDoubleTap(e) { … }
  render() { … }
}
           
Notably, we’ve dropped two parentheses and a trailing semicolon, and for each method declared we omit a colon, a function keyword, and a comma.

值得注意的是,我們删除了兩個括号和一個字尾分号,對于每個聲明的方法,我們省略了一個冒号,一個函數關鍵字和一個逗号。

All of the lifecycle methods but one can be defined as you would expect when using the new class syntax. The class’

constructor

now assumes the role previously filled by

componentWillMount

:

所有的生命周期方法,可以被定義為你會期望使用新的類文法。類的構造函數現在承擔了以前由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
    // 這裡的操作通常在componentWillMount中執行
  }
}
           

Property initializers

In the ES6+ class world, prop types and defaults live as static properties on the class itself. These, as well as the component’s initial state, can be defined using ES7 property initializers :

在ES6類世界中,prop 類型和預設值作為類本身的靜态屬性。這些,以及元件的初始狀态,可以使用ES7 property 初始化:

// The ES5 way
var Video = React.createClass({
  getDefaultProps: function() {
    return {
      autoPlay: false,
      maxLoops: ,
    };
  },
  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: ,
  }
  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 property initializers operate inside the class’ constructor, where this refers to the the instance of the class under construction, so the initial state can still be made to depend on this.props . Notably, we no longer have to define prop defaults and the initial state object in terms of a getter function.

ES7 property 初始化器在類的構造函數中操作,其中這指的是正在構造的類的執行個體,是以初始狀态仍然可以依賴于this.props。

值得注意的是,我們不再需要根據getter函數定義prop預設值和初始狀态對象。

Arrow functions

The React.createClass method used to perform some extra binding work on your component’s instance methods to make sure that, inside them, the this keyword would refer to the instance of the component in question.

React.createClass方法用于對元件的執行個體方法執行一些額外的綁定工作,以確定在其中,this關鍵字将引用有問題的元件的執行個體。

// Autobinding, brought to you by React.createClass
// 由React.createClass 自動綁定
var PostInfo = React.createClass({
  handleOptionsButtonClick: function(e) {
    // Here, 'this' refers to the component instance.
    this.setState({showOptionsModal: true});
  },
});
           
Since we don’t involve the React.createClass method when we define components using the ES6+ class syntax, it would seem that we need to manually bind instance methods wherever we want this behavior:

因為當我們使用ES6類文法定義元件時,我們不涉及React.createClass方法,是以不管我們想要什麼樣的行為都需要去手動綁定執行個體方法:

// 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});
  }
}
           
Luckily, by combining two ES6+ features – arrow functions and property initializers – opt-in binding to the component instance becomes a breeze:

幸運的是,通過組合兩個ES6特性 - 箭頭函數和屬性初始化器 - 選擇綁定到元件執行個體變得輕而易舉:

class PostInfo extends React.Component {
  handleOptionsButtonClick = (e) => {
    this.setState({showOptionsModal: true});
  }
}
           
The body of ES6 arrow functions share the same lexical this as the code that surrounds them, which gets us the desired result because of the way that ES7 property initializers are scoped.Peek under the hood to see why this works.

ES6箭頭函數的主體與它們周圍的代碼共享相同的詞法,這得到我們所期望的結果,因為ES7屬性初始化器的範圍。在引擎蓋下看看為什麼這個工作。

Dynamic property names & template strings

One of the enhancements to object literals includes the ability to assign to a derived property name. We might have originally done something like this to set a piece of state:

對對象字面量的增強之一包括配置設定給派生屬性名稱的能力。我們可能最初做了這樣的事情來設定一塊狀态:

var Form = React.createClass({
  onChange: function(inputName, e) {
    var stateToSet = {};
    stateToSet[inputName + 'Value'] = e.target.value;
    this.setState(stateToSet);
  },
});
           
Now, we have the ability to construct objects whose property names are determined by a JavaScript expression at runtime. Here, we use a template string to determine which property to set on state:

現在,我們有能力建構對象,其屬性名稱在運作時由JavaScript表達式确定。在這裡,我們使用模闆字元串來确定要設定哪個屬性的狀态:

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

Destructuring & spread attributes

Often when composing components, we might want to pass down most of a parent component’s props to a child component, but not all of them. In combining ES6+ destructuring with JSX spread attributes , this becomes possible without ceremony:

通常在編寫元件時,我們可能想将父元件的道具的大部分傳遞給子元件,但不是全部。在結合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>
    );
  }
}
           
We can combine JSX spread attributes with regular attributes too, taking advantage of a simple precedence rule to implement overrides and defaults. This element will acquire the className “override” even if there exists a className property in this.props :

我們可以組合JSX擴充屬性和正常屬性,利用一個簡單的優先級規則來實作覆寫和預設值。

此元素将擷取className“override”,即使在this.props中存在className屬性:

<div {...this.props} className="override">
  …
</div>
           
This element will regularly have the className “base” unless there exists a className property in this.props to override it:

此元素将定期具有className“base”,除非在this.props中存在className屬性以覆寫它:

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

Thanks for reading

I hope that you enjoy using ES6+ language features to write React code as much as we do. Thanks to my colleagues for their contributions to this post, and thanks especially to the Babel team for making the future available to all of us, today.

by web開發者 更多相關内容請通路: http://weber.pub/

本文位址: http://weber.pub/譯使用-es6-寫-react/335.html