React Native 入門基礎知識總結
中秋在家閑得無事,想著做點啥,後來想想,為啥不學學 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"; exportdefault 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
更改之後立刻執行。該方法包含兩個參數,分別是 props
和 state
。該方法在組件的整個生命周期可以多次執行。如果該方法返回 false
,則 componentWillUpdate(nextProps, nextState)
及其之後執行的方法都不會執行,組件則不會進行重新渲染。
shouldComponentUpdate(nextProps, nextState) { return true; }
二、在 shouldComponentUpdate(nextProps, nextState)
函數執行完畢之後立刻調用,該方法包含兩個參數,分別是 props
和 state
。render()
函數執行之前調用。該方法在組件的整個生命周期可以多次執行。
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 入門基礎知識總結