React 的ES5 語法 和 ES6 語法有何不同?


React 的ES5 語法 和 ES6 語法有何不同?

大家在用react開發項目時,常常會對react的兩種規範的語法有所困惑。今天為大家整理一下主要的幾個不同點。

系統庫的引用

ES5中的引用需要先使用require導入React包,成為對象,再去進行真正引用

<code>//ES5
var React = require("react");
var {
Component,
PropTypes
} = React; //引用React抽象組件

var ReactNative = require("react-native");
var {
Image,
Text,
} = ReactNative; //引用具體的React Native組件/<code>

在ES6裡,可以使用import方法來直接實現系統庫引用,不需要額外製作一個類庫對象

<code>//ES6
import React, {
Component,
PropTypes,
} from 'react';
import {
Image,
Text
} from 'react-native'/<code>

導出及引用單個類

ES5中,要導出一個類給別的模塊用,一般通過module.exports來實現。引用時,則依然通過require方法來獲取。

<code>//ES5導出
var MyComponent = React.createClass({
...
});
module.exports = MyComponent;

//ES5導入
var MyComponent = require('./MyComponent');/<code>

ES6中,則可以使用用export default來實現相同的功能,使用import方法來實現導入。

注意:ES5和ES6的導入導出方法是成對出現的,不可以混用。

比如:使用export default來導出,只能通過import 來導入。若使用require來導入,編譯將不能通過。

<code>//ES6導出(一般都繼承於Component類)
export default class MyComponent extends Component{
...
}

//ES6導入
import MyComponent from './MyComponent';/<code>

定義組件

ES5中,組件類的定義通過React.createClass實現。

注意:ES5中React.createClass後面是需要小括號的,且結尾必須有分號。

<code>//ES5
var Photo = React.createClass({
render: function() {
return (
<image>
);
},

});/<code>

在ES6裡,讓組件類去繼承React.Component類就可以了。

注意:這裡結尾時不會出現小括號,也不需要添加分號。

<code>//ES6
class Photo extends React.Component {
render() {
return (
<image>
);
}
}/<code>

組件內部定義方法

ES5中採用的是 ###:function()的形式,方法大括號末尾需要添加逗號。

<code>//ES5 
var Photo = React.createClass({
componentWillMount: function(){

},
render: function() {
return (
<image>
);
},
});/<code>

ES6中省略了【: function】這一段,並且結尾不需要加逗號來實現分隔。

注意:使用ES6定義的規則的話,外層必須用【class #### extend React.Component】的方式來申明這個類,否則會報錯。

<code>//ES6
class Photo extends React.Component {
componentWillMount() {


}
render() {
return (
<image>
);
}
}/<code>

定義組件的屬性類型和默認屬性

在ES5裡,屬性類型和默認屬性分別通過propTypes成員和getDefaultProps方法來實現(這兩個方法應該是固定名稱的)

<code>//ES5 
var Video = React.createClass({
getDefaultProps: function() {
return {
autoPlay: false,
maxLoops: 10,
};
},
propTypes: {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
},
render: function() {
return (
<view>
);
},
});/<code>

在ES6裡,統一使用static成員來實現

<code>//ES6
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,
}; // 注意這裡有分號
render() {
return (
<view>
);
} // 注意這裡既沒有分號也沒有逗號
}/<code>

ES6中也可以在組件類聲明完成後追加其靜態方法。雖不推薦,但寫法上也沒問題

<code>//ES6
class Video extends React.Component {
render() {
return (
<view>
);
}
}
Video.defaultProps = {
autoPlay: false,
maxLoops: 10,
};
Video.propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
};/<code>

初始化STATE

在ES5中,初始化state的方法是固定的getInitialState

<code>//ES5 
var Video = React.createClass({
getInitialState: function() {
return {
loopsRemaining: this.props.maxLoops,
};

},
})/<code>

ES6中存在兩種寫法:

第一種,直接構造state函數

<code>class Video extends React.Component {
state = {
loopsRemaining: this.props.maxLoops,
}
}/<code>

第二種,更易理解的在構造函數中初始化(這樣你還可以根據需要做一些計算)

<code>class Video extends React.Component {
constructor(props){
super(props);
this.state = {
loopsRemaining: this.props.maxLoops,
};
}
}/<code>

把方法作為回調提供

很多習慣於ES6的用戶反而不理解在ES5下可以這麼做:

<code>//ES5
var PostInfo = React.createClass({
handleOptionsButtonClick: function(e) {
// Here, 'this' refers to the component instance.
this.setState({showOptionsModal: true});
},
render: function(){
return (
<touchablehighlight>
<text>{this.props.label}/<text>
/<touchablehighlight>
)
},
});/<code>

在ES5下,React.createClass會把所有的方法都bind一遍,這樣可以提交到任意的地方作為回調函數,而this不會變化。但官方現在逐步認為這反而是不標準、不易理解的。

在ES6下,你需要通過bind來綁定this引用,或者使用箭頭函數(它會綁定當前scope的this引用)來調用

<code>//ES6
class PostInfo extends React.Component
{
handleOptionsButtonClick(e){
this.setState({showOptionsModal: true});
}
render(){
return (
<touchablehighlight> onPress={this.handleOptionsButtonClick.bind(this)}
onPress={e=>this.handleOptionsButtonClick(e)}
>
<text>{this.props.label}/<text>
/<touchablehighlight>
)
},
}/<code>

Mixins

在ES5下,我們經常使用mixin來為我們的類添加一些新的方法,譬如PureRenderMixin

<code>var PureRenderMixin = require('react-addons-pure-render-mixin');
React.createClass({
mixins: [PureRenderMixin],

render: function() {
return
foo
;
}
});/<code>

然而現在官方已經不再打算在ES6裡繼續推行Mixin,他們說:Mixins Are Dead. Long Live Composition。

儘管如果要繼續使用mixin,還是有一些第三方的方案可以用,譬如這個方案(https://github.com/brigand/react-mixin)。

不過官方推薦,對於庫編寫者而言,應當儘快放棄Mixin的編寫方式,上文中提到Sebastian Markbåge的一段代碼推薦了一種新的編碼方式:

<code>//Enhance.js
import { Component } from "React";

export var Enhance = ComposedComponent => class extends Component {
constructor() {
this.state = { data: null };
}
componentDidMount() {
this.setState({ data: 'Hello' });
}
render() {
return <composedcomponent>;
}
};/<code>
<code>//HigherOrderComponent.js
import { Enhance } from "./Enhance";

class MyComponent {
render() {
if (!this.data) return
Waiting...
;
return
{this.data}
;
}
}

export default Enhance(MyComponent); // Enhanced component/<code>

ES6+帶來的其它好處

解構&屬性延展

結合使用ES6+的解構和屬性延展,我們給孩子傳遞一批屬性更為方便了。這個例子把className以外的所有屬性傳遞給div標籤:

<code>class AutoloadingPostsGrid extends React.Component {
render() {
var {
className,
...others, // contains all properties of this.props except for className
} = this.props;
return (

<postsgrid>
<button>Load more/<button>

);
}
}/<code>

下面這種寫法,則是傳遞所有屬性的同時,用覆蓋新的className值:

<code>


/<code>

這個例子則相反,如果屬性中沒有包含className,則提供默認的值,而如果屬性中已經包含了,則使用屬性中的值

<code>


/<code>




分享到:


相關文章: