React Native 入門基礎知識總結 手把手教你實現一個完整的 Promise

中秋在家閒得無事,想着作點啥,後來想一想,爲啥不學學 react native。在學習 React Native 時, 須要對前端(HTML,CSS,JavaScript)知識有所瞭解。對於JS,能夠看看阮一峯老師的《ECMAScript 6 入門》這篇文章。裏面涉及不少 ES6 的新特性。我以前也是看了阮老師的文章作了一些學習筆記 ES6 學習筆記。 javascript

一、環境搭建

環境搭建中文教程,點擊跳轉RN中文社區 :http://reactnative.cn/docs/0.40/getting-started.html#contenthtml

社區內容講得很詳細,你們跟着操做一步一步來便可,遇到問題,直接百度。也能夠看看這篇文章:React Native 填坑指南 會教你如何把坑填平。前端

二、React Native 基礎

先來看看一個實例,這個地址源碼地址:示例教程:電影列表。之因此選擇這個例子,是由於它包含了幾乎全部的 react native入門基礎知識。java

import React, { Component } from "react";

import { Image, FlatList, StyleSheet, Text, View } from "react-native";

var REQUEST_URL =
"https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json";

export default class SampleAppMovies extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],
            loaded: false
      };
    // 在ES6中,若是在自定義的函數裏使用了this關鍵字,則須要對其進行「綁定」操做,不然this的指向會變爲空
    // 像下面這行代碼同樣,在constructor中使用bind是其中一種作法(還有一些其餘作法,如使用箭頭函數等)
    this.fetchData = this.fetchData.bind(this);
}

componentDidMount() {
    this.fetchData();
}

fetchData() {
    fetch(REQUEST_URL)
    .then(response => response.json())
    .then(responseData => {
        // 注意,這裏使用了this關鍵字,爲了保證this在調用時仍然指向當前組件,咱們須要對其進行「綁定」操做
        this.setState({
          data: this.state.data.concat(responseData.movies),
          loaded: true
      });
    });
}

render() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
  }

  return (
      <FlatList
      data={this.state.data}
      renderItem={this.renderMovie}
      style={styles.list}
      />
      );
}

renderLoadingView() {
    return (
      <View style={styles.container}>
      <Text>Loading movies...</Text>
      </View>
      );
}

renderMovie({ item }) {
    // { item }是一種「解構」寫法,請閱讀ES2015語法的相關文檔
    // item也是FlatList中固定的參數名,請閱讀FlatList的相關文檔
    return (
      <View style={styles.container}>
      <Image
      source={{ uri: item.posters.thumbnail }}
      style={styles.thumbnail}
      />
      <View style={styles.rightContainer}>
      <Text style={styles.title}>{item.title}</Text>
      <Text style={styles.year}>{item.year}</Text>
      </View>
      </View>
      );
}
}

var styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "row",
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#F5FCFF"
},
rightContainer: {
    flex: 1
},
title: {
    fontSize: 20,
    marginBottom: 8,
    textAlign: "center"
},
year: {
    textAlign: "center"
},
thumbnail: {
    width: 53,
    height: 81
},
list: {
    paddingTop: 20,
    backgroundColor: "#F5FCFF"
}
});

這個例子從電影數據庫中取得最近正在上映的 25 部電影,並在一個 FlatList 中展現出來。react

 

2.1 import 

import React,{Component} from 'react';
// 導入‘react’文件裏export的一個默認的組件,將其命名爲React以及Component這個非默認組件

還有其餘一些 import 的用法,具體含義以下:ios

    • import defaultcomponent form 'XXX'   導入 XXX 文件中的默認組件,命名爲 defaultcomponent
    • import {a} from 'XXX'   導入 XXX 文件中的 a 組件git

    • import {a as b} from 'XXX'   導入 XXX 文件中的a組件,並將其重命名爲 bes6

    • import * as a from 'XXX'   導入 XXX 文件中的全部組件,並將其命名爲 a,調用具體組件的方式爲 a.b、a.c。。。但不包含默認組件github

 

2.2 var 定義變量

在組件前面,定一個變量 REQUEST_URL 用於保存請求網址,。web

 

2.3 export 語句

模塊的功能有兩個關鍵字: export 和 import。export 用於用戶自定義模塊。import用於輸入其餘模塊的功能,同時建立命名空間(namespace),防止函數名衝突。

ES6容許將獨立的JS文件做爲模塊,也就是說,容許一個 JavaScript 腳本文件調用另外一個腳本文件。最簡單的模塊就是一個 JS 文件,裏面使用 export 關鍵字輸出變量。

    //profile.js
    export var firstName = "Pandora";
    export var lastName = "G.Dragon";
    export var year = 1973;

    //export還有下面這種寫法,二者是等價的
    var firstName = "Pandora";
    var lastName = "G.Dragon";
    var year = 1973;
    export({firstName, lastName, year});

使用 export 定義模塊以後,其餘 JS 文件就能夠經過 import 關鍵字加載這個模塊(文件)了。加載方式以下:

    import {firstName, lastName, year} from './profile';
    function setHeader(element) {
        element.textContent = firstName + '' + lastName;
    }

上面的代碼片斷中,使用了 import 關鍵字接受一個對象——用「{ }」表示。裏面指定了要從其餘模塊中導入的變量。大括號裏面的變量名必須與被導入模塊對外接口的名稱相同。

 

2.4 Class 類

ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,做爲對象的模板。經過class關鍵字,能夠定義類。基本上,ES6 的 class 能夠看做只是一個語法糖,它的絕大部分功能,ES5 均可以作到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。上面的代碼用 ES6 的「類」改寫,就是下面這樣。

//定義類
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

上面代碼定義了一個「類」,能夠看到裏面有一個 constructor 方法,這就是構造方法,而 this 關鍵字則表明實例對象。也就是說,ES5 的構造函數 Point,對應 ES6 的 Point 類的構造方法。

Point 類除了構造方法,還定義了一個 toString 方法。注意,定義「類」的方法的時候,前面不須要加上 function 這個關鍵字,直接把函數定義放進去了就能夠了。另外,方法之間不須要逗號分隔,加了會報錯。

Class 之間能夠經過 extends 關鍵字實現繼承,這比 ES5 的經過修改原型鏈實現繼承,要清晰和方便不少。

class ColorPoint extends Point {}

上面代碼定義了一個 ColorPoint 類,該類經過 extends 關鍵字,繼承了 Point 類的全部屬性和方法。可是因爲沒有部署任何代碼,因此這兩個類徹底同樣,等於複製了一個 Point 類。下面,咱們在 ColorPoint 內部加上代碼。

class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 調用父類的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 調用父類的toString()
  }
}

上面代碼中,constructor 方法和 toString 方法之中,都出現了super 關鍵字,它在這裏表示父類的構造函數,用來新建父類的 this 對象。

子類必須在 constructor 方法中調用 super 方法,不然新建實例時會報錯。這是由於子類沒有本身的 this 對象,而是繼承父類的 this 對象,而後對其進行加工。若是不調用super方法,子類就得不到 this 對象。

 

2.5 Props(屬性)

大多數組件在建立時就可使用各類參數來進行定製。用於定製的這些參數就稱爲props(屬性)。

以常見的基礎組件 Image 爲例,在建立一個圖片時,能夠傳入一個名爲 source 的 prop 來指定要顯示的圖片的地址,以及使用名爲 style 的 prop 來控制其尺寸。

import React, { Component } from 'react';
import { Image } from 'react-native';

export default class Bananas extends Component {
  render() {
    let pic = {
      uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
    };
    return (
      <Image source={pic} style={{width: 193, height: 110}} />
    );
  }
}

 

2.6 state 

 props 是在父組件中指定,並且一經指定,在被指定的組件的生命週期中則再也不改變。 對於須要改變的數據,咱們須要使用 state。

大多數組件在建立時就可使用各類參數來進行定製。用於定製的這些參數就稱爲 props(屬性)。

通常來講,你須要在 constructor 中初始化 state(譯註:這是 ES6 的寫法,早期的不少 ES5 的例子使用的是 getInitialState 方法來初始化 state,這一作法會逐漸被淘汰),而後在須要修改時調用 setState方法。

提示一些初學者應該牢記的要點:

  • 一切界面變化都是狀態 state 變化

  • state的修改必須經過 setState()方法

    • this.state.likes = 100; // 這樣的直接賦值修改無效!

    • setState 是一個 merge 合併操做,只修改指定屬性,不影響其餘屬性

    • setState 是異步操做,修改不會立刻生效

 

2.7 react native 生命週期

組件的生命週期方法對應着組件的不一樣生命階段,一般咱們分爲三個階段:組件初始化及掛載階段、組件運行期階段及組件卸載階段。

  • 初始化及掛載階段

1、這是組件類的構造函數,一般在此初始化 state 數據模型。

constructor(props) {
  super(props);
  this.state = {
    //key : value
  };
}

2、表示組件將要加載到虛擬 DOM,在 render 方法以前執行,整個生命週期只執行一次。

componentWillMount() {
}

3、表示組件已經加載到虛擬 DOM,在 render 方法以後執行,整個生命週期只執行一次。一般在該方法中完成異步網絡請求或者集成其餘 JavaScript庫。

componentDidMount() {
}
  • 運行期階段

1、在組件接收到其父組件傳遞的 props 的時候執行,參數爲父組件傳遞的props。在組件的整個生命週期能夠屢次執行。一般在此方法接收新的props值,從新設置 state

componentWillReceiveProps(nextProps) {
  this.setState({
    //key : value
  });
}

2、在 componentWillReceiveProps(nextProps) 執行以後馬上執行;或者在state更改以後馬上執行。該方法包含兩個參數,分別是 props和 state。該方法在組件的整個生命週期能夠屢次執行。若是該方法返回 false,則 componentWillUpdate(nextProps, nextState) 及其以後執行的方法都不會執行,組件則不會進行從新渲染。

shouldComponentUpdate(nextProps, nextState) {
  return true;
}

2、在 shouldComponentUpdate(nextProps, nextState) 函數執行完畢以後馬上調用,該方法包含兩個參數,分別是 props 和 staterender() 函數執行以前調用。該方法在組件的整個生命週期能夠屢次執行。

componentWillUpdate(nextProps, nextState) {

}

3、在 render() 方法執行以後馬上調用。該方法包含兩個參數,分別是 props 和 state。該方法在組件的整個生命週期能夠屢次執行。

componentDidUpdate(preProps, preState) {

}

4、render 方法用於渲染組件。在初始化階段和運行期階段都會執行。

render() {
  return(
    <View/>
  );
}
  • 卸載階段

1、在組件由虛擬 DOM 卸載的時候調用。

componentWillUnmount() {
}

 

2.8 fetch 

fetch,說白了,就是 XMLHttpRequest 的一種替代方案。若是有人問你,除了 Ajax 獲取後臺數據以外,還有沒有其餘的替代方案?答案是還可使用一種更優的解決方案 fetch。

到如今爲止,fetch 的支持性還不是很好,可是在谷歌瀏覽器中已經支持了fetch。fetch 掛在在 BOM 中,能夠直接在谷歌瀏覽器中使用。

查看 fetch 的支持狀況:fetch的支持狀況

 fetch 方法會返回一個 Promise,這種模式能夠簡化異步風格的代碼。若是你想了解 promise 的含義,能夠參考文章 :手把手教你實現一個完整的 Promise 。帶你瞭解 promise 的本質內核。

下面咱們來寫第一個 fetch 獲取後端數據的例子:

// 經過fetch獲取百度的錯誤提示頁面
fetch('https://www.baidu.com/search/error.html') // 返回一個Promise對象
  .then((res)=>{
    return res.text() // res.text()是一個Promise對象
  })
  .then((res)=>{
    console.log(res) // res是最終的結果
  })

是否是很簡單?再來看看 get 和 post 方法的使用:

// 經過fetch獲取百度的錯誤提示頁面
fetch('https://www.baidu.com/search/error.html?a=1&b=2', { // 在URL中寫上傳遞的參數
    method: 'GET'
  })

/* post 方法,把前面的 get 註釋便可
fetch('https://www.baidu.com/search/error.html', {
    method: 'POST',
    body: new URLSearchParams([["foo", 1],["bar", 2]]).toString() // 這裏是請求對象
  })
*/
  .then((res)=>{
    return res.text()
  })
  .then((res)=>{
    console.log(res)
  })

React Native 中已經內置了 XMLHttpRequest API (也就是俗稱的 ajax)。一些基於 XMLHttpRequest 封裝的第三方庫也可使用,例如 frisbee 或是 axios 等。但注意不能使用 jQuery,由於 jQuery 中還使用了不少瀏覽器中才有而 RN 中沒有的東西(因此也不是全部 web 中的 ajax 庫均可以直接使用)。

 

2.9 樣式

style 的定義方式:

  • 一、直接在 render()函數中定義
//todo 設置樣式一,直接在render中定義樣式
var mStyle = {color:'red',fontSize:34};
return<Text style={mStyle}> https://github.com/93Laer </Text>
// or 相似於安卓中的匿名內部內
// return<Text style={{color:'red',fontSize:34}}> https://github.com/93Laer </Text>
  • 二、方式二,經過 StyleSheet 建立 style,測試多個 style,以哪一個爲準
// 建立樣式
const styles = StyleSheet.create({
    bigblue:{
        color:'blue',
        fontSize:34,
        fontWeight:'bold'
    },
    red:{
        color:'red',
        fontSize:14
    }
});
// 使用樣式
//todo 設置樣式二,經過StyleSheet建立樣式
return<Text style={styles.bigblue}> https ://github.com/93Laer </Text>

直接在組件中傳入多個 style 對象,最後顯示的效果就不展現了,在結尾直接給出結論

//這裏經過多種方式定義style,主要是告訴讀者定義style的多種方式
 var mStyle = {color:'red',fontSize:34};
 return<Text style={[mStyle,{color: 'blue',fontSize:20}]}> https ://github.com/93Laer </Text>

經過 StyleSheet 建立多個 style,並傳入

 return<Text style={[styles.bigblue,styles.red]}> https ://github.com/93Laer </Text>
結論:當設置多個 style 時以最後一個爲準,可理解爲最後一個將以前的樣式覆蓋了。也可理解爲,style 從 styles 數組中依次拿出 style,並賦值給本身,因此最後一次賦值就會顯示效果

到此,關於 react native 入門的基礎知識就講解完畢了。

相關文章
相關標籤/搜索