1. 程式人生 > >React Native 入門基礎知識總結

React Native 入門基礎知識總結

入門 部署 社區 另一個 變化 started EDA set rop

中秋在家閑得無事,想著做點啥,後來想想,為啥不學學 react native。在學習 React Native 時, 需要對前端(HTML,CSS,JavaScript)知識有所了解。對於JS,可以看看阮一峰老師的《ECMAScript 6 入門》這篇文章。裏面涉及很多 ES6 的新特性。我之前也是看了阮老師的文章做了一些學習筆記 ES6 學習筆記。

1、環境搭建

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

社區內容講得很詳細,大家跟著操作一步一步來即可,遇到問題,直接百度。也可以看看這篇文章:React Native 填坑指南 會教你如何把坑填平。

2、React Native 基礎

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

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 中展示出來。

2.1 import

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

還有其他一些 import 的用法,具體含義如下:

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

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

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

2.2 var 定義變量

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

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 生命周期

組件的生命周期方法對應著組件的不同生命階段,通常我們分為三個階段:組件初始化及掛載階段、組件運行期階段及組件卸載階段。

  • 初始化及掛載階段

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

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

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

componentWillMount() {
}

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

componentDidMount() {
}
  • 運行期階段

一、在組件接收到其父組件傳遞的 props 的時候執行,參數為父組件傳遞的props。在組件的整個生命周期可以多次執行。通常在此方法接收新的props值,重新設置 state

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

二、在 componentWillReceiveProps(nextProps) 執行之後立刻執行;或者在state更改之後立刻執行。該方法包含兩個參數,分別是 propsstate。該方法在組件的整個生命周期可以多次執行。如果該方法返回 false,則 componentWillUpdate(nextProps, nextState) 及其之後執行的方法都不會執行,組件則不會進行重新渲染。

shouldComponentUpdate(nextProps, nextState) {
  return true;
}

二、在 shouldComponentUpdate(nextProps, nextState) 函數執行完畢之後立刻調用,該方法包含兩個參數,分別是 props staterender() 函數執行之前調用。該方法在組件的整個生命周期可以多次執行。

componentWillUpdate(nextProps, nextState) {

}

三、在 render() 方法執行之後立刻調用。該方法包含兩個參數,分別是 props state。該方法在組件的整個生命周期可以多次執行。

componentDidUpdate(preProps, preState) {

}

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

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

一、在組件由虛擬 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 的定義方式:

  • 1、直接在 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>
  • 2、方式二,通過 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 入門的基礎知識就講解完畢了。

React Native 入門基礎知識總結