原文地址: http://babeljs.io/blog/2015/06/07/react-on-es6-plus/javascript
在今年對 Instagram Web 進行全新的設計的時候,我喜歡在寫 React 組件的時候,用上一些 ES6+ 的新特性。請容許我列舉這些可以改變你寫 React 應用方式的新特性。比起以往,這些特性可以使你擼起碼來更加容易、有趣!java
使用 ES6+ 來編寫 React 組件最明顯的變化就是咱們定義組件(類)的語法的方式。咱們能夠用定義一個繼承了 React.Component
的ES6 類來代替本來使用 React.createClass
的來建立類的方式:react
class Photo extends React.Component { render() { return <img alt={this.props.caption} src={this.props.src} />; } }
咱們能夠發現這種寫法使得定義組件的方式變得更加簡潔:git
// The ES5 way var Photo = React.createClass({ handleDoubleTap: function(e) { … }, render: function() { … }, }); // The ES6+ way class Photo extends React.Component { handleDoubleTap(e) { … } render() { … } }
這樣咱們能夠少寫一對圓括號、一個分號、每一個方法的冒號和 function
關鍵字。es6
全部生命週期方法均可以採用這種方式來定義。 可是 componentWillMount
還能夠用 constructor
來代替:github
// 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 type
和默認屬性 default prop
能夠經過類中的 static
來聲明。同時,組件的初始狀態( initial state
)能夠經過 ES7 的屬性初始化(property initializers)來完成:babel
// 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
(即傳入的參數)來設定。ide
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
的指向:oop
// 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 團隊,使得咱們能夠隨意的使用這些特性。