標籤:
在這裡簡要的說一下這些語言新特性對 React 應用的開發有什麼影響,這些 ES6+ 特性使得 React 開發更簡單更有趣。
類
迄今為止,最能體現我們使用 ES6+ 來編寫 React 組件的就是我們選擇使用類定義文法。替代了使用 React.createClass 方法來定義一個組件,我們可以定義一個 bonafide ES6 類來擴充 React.Component:
?
12345 |
class Photo extends React.Component { render() { return <img alt={ this .props.caption} src={ this .props.src} />; } } |
現在,你就會發現一個微妙的差異 —— 當使用定義類的時候文法更簡潔:
?
12345 |
// The ES5 way var Photo = React.createClass({ handleDoubleTap: function (e) { … }, render: function () { … }, }); |
?
12345 |
// The ES6+ way class Photo extends React.Component { handleDoubleTap(e) { … } render() { … } } |
值得關注的是,我們去掉了兩個括弧和一個分號,每個方法聲明我們省略了一個冒號,一個關鍵字和一個分號。
當使用新的類定義時,所有的生命週期方法至少有一個是符合你期望的。類的 constructor 現在假設 role 之前是通過 componentWillMount 填充的:
?
1234 |
// The ES5 way var EmbedModal = React.createClass({ componentWillMount: function () { … }, }); |
?
1234567 |
// 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 定義:
?
1234567891011121314151617181920 |
// 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, }, }); |
?
12345678910111213141516 |
// 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 關鍵字會指向組件執行個體:
?
1234567 |
// 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+ 類文法定義組件,看似需要手動綁定執行個體方法:
?
123456789101112 |
// 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 和屬性初始化程式 – 可以選擇綁定組件執行個體:
?
12345 |
class PostInfo extends React.Component { handleOptionsButtonClick = (e) => { this .setState({showOptionsModal: true }); } } |
ES6 的 arrow 函數體分享相同的詞 this,用這來圍繞他們的代碼,這些可以達到我們預期的結果,也是 ES7 屬性初始化程式在域內的方式。 Peek under the hood 來看看為什麼能實現。
動態屬性名稱 & 模板字串
其中一個對象常量增強是可以分配到一個派生屬性名稱。我們最初可能會像下面這樣設定一些狀態:
?
1234567 |
var Form = React.createClass({ onChange: function (inputName, e) { var stateToSet = {}; stateToSet[inputName + ‘Value‘ ] = e.target.value; this .setState(stateToSet); }, }); |
現在,我們有能力構造通過一個運行時 JavaScript 運算式確定屬性名稱的對象。這裡,我們使用了一個模板字串來確定哪個屬性設定狀態:
?
1234567 |
class Form extends React.Component { onChange(inputName, e) { this .setState({ [`${inputName}Value`]: e.target.value, }); } } |
解構 & 傳播屬性
通常在編寫組件的時候,我們可能想把大部分父組件的 props 傳遞給子組件,但不是所有。結合 ES6+ 解構和 JSX 傳播屬性,這個不需要多餘的部分就能實現:
?
1234567891011121314 |
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 屬性:
?
123 |
<div {... this .props} className= "override" > … </div> |
這個元素常規來說需要 className “base” ,除非 this.props 有 className 屬性覆蓋:
?
123 |
<div className= "base" {... this .props}> … </div> |
希望大家能享受 ES6+ 語言特性給 React 開發帶來的一些便利。
ES6+ 開發 React 組件