React Native之React速學教程(下)

React Native之React速學教程(下)

本文出自《React Native學習筆記》系列文章。

React Native是基于React的,在開發(fā)React Native過程中少不了的需要用到React方面的知識艺沼。雖然官方也有相應的Document,但篇幅比較多,學起來比較枯燥棘捣。
通過《React Native之React速學教程》你可以對React有更系統(tǒng)和更深入的認識。為了方便大家學習休建,我將《React Native之React速學教程》分為乍恐、三篇测砂,大家可以根據(jù)需要進行閱讀學習茵烈。

概述

本篇為《React Native之React速學教程》的最后一篇。本篇將帶著大家一起認識ES6砌些,學習在開發(fā)中常用的一些ES6的新特性呜投,以及ES6與ES5的區(qū)別加匈,解決大家在學習React /React Native過程中對于ES6與ES5的一些困惑。

ES6的特性

何為ES6仑荐?

ES6全稱ECMAScript 6.0雕拼,ES6于2015年6月17日發(fā)布,ECMAScript是ECMA制定的標準化腳本語言粘招。目前JavaScript使用的ECMAScript版本為ECMAScript-262啥寇。

下面我為大家列舉了ES6新特性中對我們開發(fā)影響比較大的六方面的特性。

1.類(class)

對熟悉Java洒扎,object-c示姿,c#等純面向對象語言的開發(fā)者來說,都會對class有一種特殊的情懷逊笆。ES6 引入了class(類)栈戳,讓JavaScript的面向對象編程變得更加簡單和易于理解。

  class Animal {
    // 構造方法难裆,實例化的時候將會被調用子檀,如果不指定,那么會有一個不帶參數(shù)的默認構造函數(shù).
    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 來規(guī)定模塊對外暴露的接口习贫,通過import來引用其它模塊提供的接口逛球。同時還為模塊創(chuàng)造了命名空間,防止函數(shù)的命名沖突苫昌。

導出(export)

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

導出變量

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

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

ES6將一個文件視為一個模塊奥务,上面的模塊通過 export 向外輸出了一個變量。一個模塊也可以同時往外面輸出多個變量袜硫。

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

導出函數(shù)

// 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)函數(shù)

這是ES6中最令人激動的特性之一父款。=>不只是關鍵字function的簡寫溢谤,它還帶來了其它好處。箭頭函數(shù)與包圍它的代碼共享同一個this,能幫你很好的解決this的指向問題憨攒。有經驗的JavaScript開發(fā)者都熟悉諸如var self = this;var that = this這種引用外圍this的模式世杀。但借助=>,就不需要這種模式了肝集。

箭頭函數(shù)的結構

箭頭函數(shù)的箭頭=>之前是一個空括號瞻坝、單個的參數(shù)名、或用括號括起的多個參數(shù)名杏瞻,而箭頭之后可以是一個表達式(作為函數(shù)的返回值)所刀,或者是用花括號括起的函數(shù)體(需要自行通過return來返回值,否則返回的是undefined)捞挥。

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

心得:不論是箭頭函數(shù)還是bind浮创,每次被執(zhí)行都返回的是一個新的函數(shù)引用,因此如果你還需要函數(shù)的引用去做一些別的事情(譬如卸載監(jiān)聽器)砌函,那么你必須自己保存這個引用斩披。

卸載監(jiān)聽器時的陷阱

錯誤的做法

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還是箭頭函數(shù)垦沉,每次被執(zhí)行都返回的是一個新的函數(shù)引用,因此如果你還需要函數(shù)的引用去做一些別的事情(譬如卸載監(jiān)聽器)仍劈,那么你必須自己保存這個引用厕倍。

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

用一個“增強組件”芍躏,來為某個類增加一些方法邪乍,并且返回一個新類,這無疑能實現(xiàn)mixin所實現(xiàn)的大部分需求对竣。

另外庇楞,網上也有很多其他的方案,如react-mixin否纬。

5.ES6不再有自動綁定

在ES5中吕晌,React.createClass會把所有的方法都bind一遍,這樣可以提交到任意的地方作為回調函數(shù)临燃,而this不會變化睛驳。但在ES6中沒有了自動綁定烙心,也就是說,你需要通過bind或者箭頭函數(shù)來手動綁定this引用乏沸。

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

心得: 因為無論是箭頭函數(shù)還是bind()每次被執(zhí)行都返回的是一個新的函數(shù)引用淫茵,所以,推薦大家在組件的構造函數(shù)中來綁定this蹬跃。

constructor(props) {
super(props);
this.state = {count: props.initialCount};
this.tick = this.tick.bind(this);//在構造函數(shù)中綁定this
}
// 使用
<div onClick={this.tick}>


### 6.static關鍵字

在ES6中我們可以通過static關鍵字來定義一個類函數(shù)匙瘪。  

```javascript
class People {
    constructor(name) { //構造函數(shù)
          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的區(qū)別)

新版本的React /React Native使用了ES6標準,下面就讓我們一起了解一下基于ES6的React/React Native相比ES5有哪些不同蝶缀。

心得:很多React/React Native的初學者經常會被ES6問題迷惑:官方建議我們ES6丹喻,但是網上搜到的很多教程和例子都是基于ES5版本的,所以很多人感覺無法下手翁都,下面就讓我們一起認識ES6與ES5在React/React Native開發(fā)上有哪些不同和需要注意的地方碍论。

下面是我們需要知道的ES6與ES5在4大方面上的區(qū)別。

1.在定義方面的不同

在定義組件柄慰,方法骑冗,屬性等方面,ES6與ES5是有所不同的先煎,下面就讓我們一起看一下有哪些不同贼涩。

心得:因為向下兼容的原因,你在開發(fā)過程中可使用ES6也可以使用ES5的規(guī)范薯蝎,但為了代碼的風格一致性遥倦,建議盡量減少混寫。

定義組件

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方法來實現(xiàn)。

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里伤提,可以統(tǒng)一使用static成員來實現(xiàn)巫俺。

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開發(fā)者而言介汹,static在一些老版本的瀏覽器上是不支持的却嗡。React Native開發(fā)者可以不用擔心這個問題。

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 ”修飾是有本質區(qū)別的恐锣,使用的時候要特別注意。

導出組件

ES5
在ES5里舞痰,要導出一個類給別的模塊用土榴,一般通過module.exports來導出:

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

ES6
在ES6里,通常用export default來實現(xiàn)相同的功能:

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

不過我們推薦更易理解的在構造函數(shù)中初始化(這樣你還可以根據(jù)需要做一些計算):

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

4.在方法作為回調上的不同

在開發(fā)工作中玷禽,經常會使用到回調,如按鈕的單擊回調等呀打,這也是在很多編程語言中都會經常出現(xiàn)的情況论衍。ES6與ES5在使用回調方面是有區(qū)別的。

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一遍坯台,這樣可以提交到任意的地方作為回調函數(shù),而this不會變化瘫寝。但官方現(xiàn)在逐步認為這反而是不標準蜒蕾、不易理解的稠炬。

在ES6下,你需要通過bind來綁定this引用咪啡,或者使用箭頭函數(shù)(它會綁定當前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>
        )
    },·
}

參考

React's official site
React on ES6+

About

本文出自《React Native學習筆記》系列文章首启。
了解更多,可以關注我的GitHub
@http://jiapenghui.com

推薦閱讀

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末毅桃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子准夷,更是在濱河造成了極大的恐慌钥飞,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衫嵌,死亡現(xiàn)場離奇詭異读宙,居然都是意外死亡,警方通過查閱死者的電腦和手機楔绞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門结闸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人酒朵,你說我怎么就攤上這事桦锄。” “怎么了蔫耽?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵结耀,是天一觀的道長。 經常有香客問我针肥,道長饼记,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任慰枕,我火速辦了婚禮具则,結果婚禮上,老公的妹妹穿的比我還像新娘具帮。我一直安慰自己博肋,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布蜂厅。 她就那樣靜靜地躺著匪凡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掘猿。 梳的紋絲不亂的頭發(fā)上病游,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音,去河邊找鬼衬衬。 笑死买猖,一個胖子當著我的面吹牛,可吹牛的內容都是我干的滋尉。 我是一名探鬼主播玉控,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼狮惜!你這毒婦竟也來了高诺?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤碾篡,失蹤者是張志新(化名)和其女友劉穎虱而,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耽梅,經...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡薛窥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年胖烛,在試婚紗的時候發(fā)現(xiàn)自己被綠了眼姐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡佩番,死狀恐怖众旗,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情趟畏,我是刑警寧澤贡歧,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站赋秀,受9級特大地震影響利朵,放射性物質發(fā)生泄漏。R本人自食惡果不足惜猎莲,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一绍弟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧著洼,春花似錦樟遣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至液荸,卻和暖如春瞻佛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背娇钱。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工伤柄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留涡尘,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓响迂,卻偏偏與公主長得像考抄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蔗彤,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內容