React Native的語法之ES5和ES6

原文地址:http://www.devio.org/2016/08/11/React-Native%E4%B9%8BReact%E9%80%9F%E5%AD%A6%E6%95%99%E7%A8%8B-(%E4%B8%8B)/javascript

ES6的特性

何爲ES6?

ES6全稱ECMAScript 6.0,ES6於2015年6月17日發佈,ECMAScript是ECMA制定的標準化腳本語言。目前JavaScript使用的ECMAScript版本爲ECMAScript-262。java

下面我爲你們列舉了ES6新特性中對咱們開發影響比較大的六方面的特性。react

1.類(class)

對熟悉Java,object-c,c#等純面嚮對象語言的開發者來講,都會對class有一種特殊的情懷。ES6 引入了class(類),讓JavaScript的面向對象編程變得更加簡單和易於理解。git

class Animal { // 構造方法,實例化的時候將會被調用,若是不指定,那麼會有一個不帶參數的默認構造函數. constructor(name,color) { this.name = name; this.color = color; } // toString 是原型對象上的屬性 toString() { console.log('name:' + this.name + ',color:' + this.color); } } var animal = new Animal('dog','white');//實例化Animal animal.toString(); console.log(animal.hasOwnProperty('name')); //true console.log(animal.hasOwnProperty('toString')); // false console.log(animal.__proto__.hasOwnProperty('toString')); // true class Cat extends Animal { constructor(action) { // 子類必需要在constructor中指定super 方法,不然在新建實例的時候會報錯. // 若是沒有置頂consructor,默認帶super方法的constructor將會被添加、 super('cat','white'); this.action = action; } toString() { console.log(super.toString()); } } var cat = new Cat('catch') cat.toString(); // 實例cat 是 Cat 和 Animal 的實例,和Es5徹底一致。 console.log(cat instanceof Cat); // true console.log(cat instanceof Animal); // true 

2.模塊(Module)

ES5不支持原生的模塊化,在ES6中,模塊將做爲重要的組成部分被添加進來。模塊的功能主要由 export 和 import 組成。每個模塊都有本身單獨的做用域,模塊之間的相互調用關係是經過 export 來規定模塊對外暴露的接口,經過import來引用其它模塊提供的接口。同時還爲模塊創造了命名空間,防止函數的命名衝突。es6

導出(export)

ES6容許在一個模塊中使用export來導出多個變量或方法。github

導出變量編程

//test.js export var name = 'Rainbow' 

心得:ES6不只支持變量的導出,也支持常量的導出。 export const sqrt = Math.sqrt;//導出常量c#

ES6將一個文件視爲一個模塊,上面的模塊經過 export 向外輸出了一個變量。一個模塊也能夠同時往外面輸出多個變量。react-native

//test.js var name = 'Rainbow'; var age = '24'; export {name, age}; 

導出函數瀏覽器

// myModule.js export function myModule(someArg) { return someArg; } 

導入(import)

定義好模塊的輸出之後就能夠在另一個模塊經過import引用。

import {myModule} from 'myModule';// main.js import {name,age} from 'test';// test.js 

心得:一條import 語句能夠同時導入默認方法和其它變量。import defaultMethod, { otherMethod } from 'xxx.js';

3.箭頭(Arrow)函數

這是ES6中最使人激動的特性之一。=>不僅是關鍵字function的簡寫,它還帶來了其它好處。箭頭函數與包圍它的代碼共享同一個this,能幫你很好的解決this的指向問題。有經驗的JavaScript開發者都熟悉諸如var self = this;var that = this這種引用外圍this的模式。但藉助=>,就不須要這種模式了。

箭頭函數的結構

箭頭函數的箭頭=>以前是一個空括號、單個的參數名、或用括號括起的多個參數名,而箭頭以後能夠是一個表達式(做爲函數的返回值),或者是用花括號括起的函數體(須要自行經過return來返回值,不然返回的是undefined)。

// 箭頭函數的例子 ()=>1 v=>v+1 (a,b)=>a+b ()=>{ alert("foo"); } e=>{ if (e == 0){ return 0; } return 1000/e; } 

心得:不管是箭頭函數仍是bind,每次被執行都返回的是一個新的函數引用,所以若是你還須要函數的引用去作一些別的事情(譬如卸載監聽器),那麼你必須本身保存這個引用。

卸載監聽器時的陷阱

錯誤的作法

class PauseMenu extends React.Component{ componentWillMount(){ AppStateIOS.addEventListener('change', this.onAppPaused.bind(this)); } componentWillUnmount(){ AppStateIOS.removeEventListener('change', this.onAppPaused.bind(this)); } onAppPaused(event){ } } 

正確的作法

class PauseMenu extends React.Component{ constructor(props){ super(props); this._onAppPaused = this.onAppPaused.bind(this); } componentWillMount(){ AppStateIOS.addEventListener('change', this._onAppPaused); } componentWillUnmount(){ AppStateIOS.removeEventListener('change', this._onAppPaused); } onAppPaused(event){ } } 

除上述的作法外,咱們還能夠這樣作:

class PauseMenu extends React.Component{ componentWillMount(){ AppStateIOS.addEventListener('change', this.onAppPaused); } componentWillUnmount(){ AppStateIOS.removeEventListener('change', this.onAppPaused); } onAppPaused = (event) => { //把方法直接做爲一個arrow function的屬性來定義,初始化的時候就綁定好了this指針 } } 

須要注意的是:不管是bind仍是箭頭函數,每次被執行都返回的是一個新的函數引用,所以若是你還須要函數的引用去作一些別的事情(譬如卸載監聽器),那麼你必須本身保存這個引用。

4.ES6再也不支持Mixins

在ES5下,咱們常用mixin來爲組件添加一些新的方法,如:

var SetIntervalMixin = { componentWillMount: function() { this.intervals = []; }, setInterval: function() { this.intervals.push(setInterval.apply(null, arguments)); }, componentWillUnmount: function() { this.intervals.forEach(clearInterval); } }; var TickTock = React.createClass({ mixins: [SetIntervalMixin], // Use the mixin getInitialState: function() { return {seconds: 0}; }, ... 

但,很不幸的是,ES6不支持使用Mixins了,不過咱們可使用,加強組件來替代Mixins。

//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 {...this.props} data={this.state.data} />; } }; //HigherOrderComponent.js import { Enhance } from "./Enhance"; class MyComponent { render() { if (!this.data) return <div>Waiting...</div>; return <div>{this.data}</div>; } } export default Enhance(MyComponent); // Enhanced component 

用一個「加強組件」,來爲某個類增長一些方法,而且返回一個新類,這無疑能實現mixin所實現的大部分需求。

另外,網上也有不少其餘的方案,如react-mixin

5.ES6再也不有自動綁定

在ES5中,React.createClass會把全部的方法都bind一遍,這樣能夠提交到任意的地方做爲回調函數,而this不會變化。但在ES6中沒有了自動綁定,也就是說,你須要經過bind或者箭頭函數來手動綁定this引用。

// 經過使用 bind() 來綁定`this` <div onClick={this.tick.bind(this)}> // 也可經過使用箭頭函數來實現 <div onClick={() => this.tick()}> 

心得: 由於不管是箭頭函數仍是bind()每次被執行都返回的是一個新的函數引用,因此,推薦你們在組件的構造函數中來綁定this

```javascript constructor(props) { super(props); this.state = {count: props.initialCount}; this.tick = this.tick.bind(this);//在構造函數中綁定this } // 使用

<div onClick={this.tick}>

### 6.static關鍵字

在ES6中咱們能夠經過static關鍵字來定義一個類函數。  

```javascript
class People {
    constructor(name) { //構造函數
          this.name = name;
    }
    sayName() {
          console.log(this.name);
    }
    static formatName(name) //將formatName定義爲類方法
        return name[0].toUpperCase() + name.sustr(1).toLowerCase();
    }
}
console.log(People.formatName("tom")); //使用類方法formatName 

ES6 VS ES5(ES6與ES5的區別)

新版本的React /React Native使用了ES6標準,下面就讓咱們一塊兒瞭解一下基於ES6的React/React Native相比ES5有哪些不一樣。

心得:不少React/React Native的初學者常常會被ES6問題迷惑:官方建議咱們ES6,可是網上搜到的不少教程和例子都是基於ES5版本的,因此不少人感受沒法下手,下面就讓咱們一塊兒認識ES6與ES5在React/React Native開發上有哪些不一樣和須要注意的地方。

下面是咱們須要知道的ES6與ES5在4大方面上的區別。

1.在定義方面的不一樣

在定義組件,方法,屬性等方面,ES6與ES5是有所不一樣的,下面就讓咱們一塊兒看一下有哪些不一樣。

心得:由於向下兼容的緣由,你在開發過程當中可以使用ES6也可使用ES5的規範,但爲了代碼的風格一致性,建議儘可能減小混寫。

定義組件

ES5

在ES5裏,一般經過React.createClass來定義一個組件類,像這樣:

var Photo = React.createClass({ render: function() { return ( <Image source={this.props.source} /> ); }, }); 

ES6

在ES6裏,咱們經過繼承React.Component 來定義一個組件類,像這樣:

class Photo extends React.Component { render() { return ( <Image source={this.props.source} /> ); } } 

定義方法

相比ES5,ES6在方法定義上語法更加簡潔,從上面的例子裏能夠看到,給組件定義方法再也不用 名字: function()的寫法,而是直接用名字(),在方法的最後也不能有逗號了。

ES5

var Photo = React.createClass({ test: function(){ }, render: function() { return ( <Image source={this.props.source} /> ); }, }); 

ES6

class Photo extends React.Component { test() { } render() { return ( <Image source={this.props.source} /> ); } } 

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

ES5

在ES5裏,屬性類型和默認屬性分別經過propTypes成員和getDefaultProps方法來實現。

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

ES6

在ES6裏,能夠統一使用static成員來實現。

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 /> ); } // 注意這裏既沒有分號也沒有逗號 } 

也有人這麼寫,雖然不推薦,但讀到代碼的時候你應當能明白它的意思:

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

心得:對React開發者而言,static在一些老版本的瀏覽器上是不支持的。React Native開發者能夠不用擔憂這個問題。

2.在導入(import)與導出(export)組件上的不一樣

導入組件

ES5

在ES5裏,若是使用CommonJS標準,引入React包基本經過require進行,代碼相似這樣:

var React = require("react"); var { Component, PropTypes } = React; //引用React抽象組件 
var ReactNative = require("react-native"); var { Image, Text, } = ReactNative; //引用具體的React Native組件 
var AboutPage=require('./app/AboutPage') //引入app目錄下AboutPage組件,即AboutPag.js var PopularPage=require('./app/PopularPage') //引入app目錄下PopularPage組件,即PopularPage.js var FavoritePage=require('./app/FavoritePage') //引入app目錄下FavoritePage組件,即FavoritePage.js 

ES6

在ES6裏,沒有了require,而是使用import來導入組件,有點像Java的寫法。

import React, { Component, PropTypes, } from 'react';//引用React抽象組件 
import { Image, Text } from 'react-native' //引用具體的React Native組件 
import AboutPage from './app/AboutPage' //引入app目錄下AboutPage組件,即AboutPag.js import PopularPage from './app/PopularPage' //引入app目錄下PopularPage組件,即PopularPage.js import FavoritePage from './app/FavoritePage' //引入app目錄下FavoritePage組件,即FavoritePage.js 

另外,ES6支持將組件導入做爲一個對象,使用「 * as」修飾便可。

//引入app目錄下AboutPage組件做爲一個對象,接下來就可以使用「AboutPage.」來調用AboutPage的方法及屬性了。 import * as AboutPage from './app/AboutPage' 

心得:使用「 * as 」修飾後,導入的組件直接被實例化成一個對象,可使用「.」語法來調用組件的方法和屬性,和沒有「 * as 」修飾是有本質區別的,使用的時候要特別注意。

導出組件

ES5
在ES5裏,要導出一個類給別的模塊用,通常經過module.exports來導出:

var MyComponent = React.createClass({ ... }); module.exports = MyComponent; 

ES6
在ES6裏,一般用export default來實現相同的功能:

export default class MyComponent extends Component{ ... } 

3.在初始化state上的不一樣

ES5

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

ES6
ES6下,有兩種寫法:

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

不過咱們推薦更易理解的在構造函數中初始化(這樣你還能夠根據須要作一些計算):

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

4.在方法做爲回調上的不一樣

在開發工做中,常常會使用到回調,如按鈕的單擊回調等,這也是在不少編程語言中都會常常出現的狀況。ES6與ES5在使用回調方面是有區別的。

ES5

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

在ES5中,React.createClass會把全部的方法都bind一遍,這樣能夠提交到任意的地方做爲回調函數,而this不會變化。但官方如今逐步認爲這反而是不標準、不易理解的。

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

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> ) },· }
相關文章
相關標籤/搜索