整理了一下關(guān)于 React Native 入門內(nèi)容,僅供參考,如有問(wèn)題,還請(qǐng)指出。
React Native (簡(jiǎn)稱RN)是Facebook于2015年4月開源的跨平臺(tái)移動(dòng)應(yīng)用開發(fā)框架,是Facebook早先開源的UI框架 React 在原生移動(dòng)應(yīng)用平臺(tái)的衍生產(chǎn)物,目前支持iOS和安卓?jī)纱笃脚_(tái)。RN使用Javascript語(yǔ)言,類似于HTML的JSX,以及CSS來(lái)開發(fā)移動(dòng)應(yīng)用,因此熟悉Web前端開發(fā)的技術(shù)人員只需很少的學(xué)習(xí)就可以進(jìn)入移動(dòng)應(yīng)用開發(fā)領(lǐng)域。
React Native使你能夠在Javascript和React的基礎(chǔ)上獲得完全一致的開發(fā)體驗(yàn),構(gòu)建世界一流的原生APP。
React Native著力于提高多平臺(tái)開發(fā)的開發(fā)效率 —— 僅需學(xué)習(xí)一次,編寫任何平臺(tái)。(Learn once, write anywhere)。
Facebook已經(jīng)在多項(xiàng)產(chǎn)品中使用了React Native,并且將持續(xù)地投入建設(shè)React Native。
React Native主要特性如下:
- 原生的iOS組件
React Native主張“Learn once, write everywhere”而非其他跨平臺(tái)工具一直宣揚(yáng)的“Write once, run everywhere”。通過(guò)React Native,開發(fā)者可以使用UITabBar、UINavigationController等標(biāo)準(zhǔn)的iOS平臺(tái)組件,讓應(yīng)用界面在其他平臺(tái)上亦能保持始終如一的外觀、風(fēng)格。
- 異步執(zhí)行
JavaScript應(yīng)用代碼和原生平臺(tái)之間所有的操作都采用異步執(zhí)行模式,原生模塊使用額外線程,開發(fā)者可以解碼主線程圖像、后臺(tái)保存至磁盤、無(wú)須顧忌UI等諸多因素直接度量文本設(shè)計(jì)布局。
- 觸摸處理
React Native引入了一個(gè)類似于iOS上Responder Chain響應(yīng)鏈?zhǔn)录幚頇C(jī)制的響應(yīng)體系,并基于此為開發(fā)者提供了諸如TouchableHighlight等更高級(jí)的組件。
要學(xué)好React Native開發(fā)要學(xué)習(xí)些什么呢?
- Html+CSS+JavaScript的基本功肯定是少不了;
- Node.js的基本概念學(xué)習(xí)。API文檔:https://nodejs.org/dist/v4.2.2/docs/api/
- JSX: JavaScript語(yǔ)法的一個(gè)擴(kuò)展,類似XML結(jié)構(gòu)。https://facebook.github.io/react/docs/jsx-in-depth.html
- FLUX: Facebook公司的一個(gè)創(chuàng)建用戶客戶端web程序的框架。https://facebook.github.io/flux/docs/overview.html
React Native文檔:
系統(tǒng)環(huán)境配置:
初始化項(xiàng)目:
首先創(chuàng)建一個(gè)項(xiàng)目:
cd /Users/cj/Desktop/RN
react-native init CJFirstRN
CJFirstRN 是項(xiàng)目名,該命令會(huì)創(chuàng)建一個(gè)名為 CJFirstRN 的文件夾,其中是一些依賴包,入口文件,項(xiàng)目工程文件等
稍等一會(huì)...
初始化項(xiàng)目完成之后,你可以選擇兩種不同的方式運(yùn)行 App 在 iOS/Android 平臺(tái):
To run your app on iOS:
cd /Users/cj/Desktop/RN/CJFirstRN
react-native run-ios
- or -
Open ios/CJFirstRN.xcodeproj in Xcode
Hit the Run button
To run your app on Android:
cd /Users/cj/Desktop/RN/CJFirstRN
Have an Android emulator running (quickest way to get started), or a device connected
react-native run-android
下面這張圖內(nèi)是項(xiàng)目的所有內(nèi)容:
綠色框內(nèi)的兩個(gè)文件 index.ios.js/index.android.js 對(duì)應(yīng)的是 iOS/Android 的入口文件;
node_modules文件夾里是依賴包;
ios、android文件夾中是各自的工程文件;
package.json類似于 iOS 內(nèi)的podfile;
app.json是項(xiàng)目的一些配置信息。
以 iOS 為例,打開 index.ios.js 文件,查看一些模板代碼,下面是代碼和他們的意思:
/*
第一部分
導(dǎo)入React Native包,導(dǎo)入React Native組件
AppRegistry:JS運(yùn)行所有React Native應(yīng)用的入口
StyleSheet:React Native中使用的樣式表,類似CSS樣式表
各種開發(fā)中需要使用的組件
模板中使用的是ES6語(yǔ)法,ES5語(yǔ)法如下
let React = require("react-native");
let {
AppRegistry,
StyleSheet,
Text,
View
} = React
require函數(shù),搜索目錄加載文件
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
/*
第二部分
創(chuàng)建React Native組件
這是默認(rèn)的載入類,繼承自Component,Component類似于Android-View和iOS-UIView
當(dāng)一個(gè)組件要顯示的時(shí)候,會(huì)自動(dòng)調(diào)用render()去渲染組件
模板中使用的是ES6語(yǔ)法,
render(){}是ES6的函數(shù)簡(jiǎn)寫
ES5語(yǔ)法如下:
var HelloWorld = React.createClass({
render:function{
return {};
}
});
*/
export default class HelloWorld extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
);
}
}
/*
第三部分
StyleSheet.create創(chuàng)建樣式實(shí)例
在應(yīng)用中只會(huì)創(chuàng)建一次,不用每次在渲染周期中重新創(chuàng)建
*/
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
/*
第四部分
注冊(cè)入口組件
AppRegistry:負(fù)責(zé)注冊(cè)運(yùn)行React Native應(yīng)用程序的JavaScript入口
registerComponent注冊(cè)應(yīng)用程序的入口組件。告知React Native哪一個(gè)組件被注冊(cè)為應(yīng)用的根容器
第一個(gè)是模塊名稱,類似于"key",和 iOS AppDelegate 里面的一樣,Android的我沒(méi)看ㄟ( ▔, ▔ )ㄏ
第二個(gè)參數(shù)使用了ES6語(yǔ)法,箭頭函數(shù):
() => HelloWorld
=> 左邊是函數(shù)參數(shù),右邊是函數(shù)返回值
返回的必須是定義的組件類的名字
等價(jià)于
function() {
return HelloWorld
}
*/
AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
看到這,你應(yīng)該也明白了各個(gè)模塊的作用,接下來(lái)我們來(lái)了解一些 React Native 開發(fā)基礎(chǔ)。
React Native 開發(fā)基礎(chǔ)
什么是JavaScript?
JS是一個(gè)輕量級(jí)的,解釋型的講函數(shù)視為一級(jí)公民的程序設(shè)計(jì)語(yǔ)言。它是一種基于原型的多范式動(dòng)態(tài)腳本語(yǔ)言,支持面向?qū)ο螅钍骄幊毯秃瘮?shù)式編程。
JavaScript的標(biāo)準(zhǔn)是 ECMAScript,React Native的語(yǔ)法是基于ECMAScript 6,簡(jiǎn)稱ES6。
聲明:
- var 聲明變量,可以在聲明的時(shí)候初始化為一個(gè),可以修改,如果不初始化會(huì)輸出undefined,不會(huì)報(bào)錯(cuò)。
- let 聲明塊范圍局部變量,可以在聲明的時(shí)候初始化一個(gè)值,函數(shù)內(nèi)部使用let定義后,對(duì)函數(shù)外部無(wú)影響。
- const 聲明一個(gè)只讀常量,不可以修改,而且必須初始化。
Tips:JS是大小寫敏感的。
變量、常量:
- 命名要以數(shù)字字母下劃線開頭
Tips:JS是一個(gè)動(dòng)態(tài)類型語(yǔ)言(dynamically typed language)中,所以變量不需聲明類型,必要的時(shí)候自動(dòng)轉(zhuǎn)換。
例如,在 class HelloWorld上 添加兩行
var mainText = "我真帥"
var subText = "嗯,沒(méi)毛病!"
然后,讓Text來(lái)顯示這個(gè)這兩個(gè)變量
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
{mainText}
</Text>
<Text style={styles.instructions}>
{subText}
</Text>
</View>
);
}
command+R刷新,效果圖如下:
常量可以看到index.ios.js文件最下面有類似:
const styles = StyleSheet.create({
...
});
就是一個(gè)常量,記住在聲明的時(shí)候,必須初始化。
數(shù)據(jù)結(jié)構(gòu)和類型:
- 六種基本的原型數(shù)據(jù)類型
Boolean:布爾值,true或者false
null:一個(gè)表明null的特殊關(guān)鍵字,注意JS中大小寫敏感,null和NULL是完全不同的東西
undefined:屬性未定義的變量
Number:數(shù)字
String:字符串
Symbol :ES6中新增的,唯一不可變的
- 以及Object類型
流程控制:
if,else
switch
for
while
break
continue
這個(gè)各個(gè)語(yǔ)言大同小異,不浪費(fèi)篇幅了,有一點(diǎn)要提一下,JS中的Switch Case中可以是String。
有一點(diǎn)要注意,以下值在JS中是會(huì)識(shí)別為false:
false
undefined
null
0
NaN
空字符串 ("")
注釋:
// 這是一個(gè)單行注釋。
/* 這是一個(gè)多行注釋。它可以是任意長(zhǎng)度,你可以在這里隨便寫什么。 */
Promises:
- 從ES6開始,JS中引入了Promises來(lái)處理異步和延遲操作,在React Native的網(wǎng)絡(luò)請(qǐng)求中是很常見的。
- 一個(gè)promise有以下幾種狀態(tài)
pending:最初的狀態(tài)
fulfilled:執(zhí)行失敗
rejected:執(zhí)行成功
settled:執(zhí)行結(jié)束了,失敗(rejected)或者成功(fulfilled)
控制圖如下:
函數(shù):
函數(shù)的定義如下,由function關(guān)鍵字聲明,在()添加輸入,輸入不需要聲明類型
function globalFunc(str){
alert(str);
}
我們接著上述的工程,添加一個(gè)可點(diǎn)擊的TouchableHighLight
。
在 import 中,添加一行TouchableHighlight
,然后重新定義變量和類的內(nèi)容:
var mainText = "點(diǎn)擊屏幕任意位置"
function globalFunc(str){
alert(str);
}
export default class CJFirstRN extends Component {
render() {
return (
<TouchableHighlight
onPress={() => globalFunc("哈哈哈")}
underlayColor = '#ddd'
style = {styles.container}
>
<Text style={styles.welcome}>{mainText}</Text>
</TouchableHighlight>
);
}
}
command+R刷新,點(diǎn)擊屏幕效果圖如下:
這樣的方法是定義在全局的,當(dāng)在類中定義的時(shí)候,不需要funciton關(guān)鍵字。
在類中定義通過(guò)this.functionName來(lái)訪問(wèn):
var mainText = "點(diǎn)擊屏幕任意位置"
export default class CJFirstRN extends Component {
render() {
return (
<TouchableHighlight
onPress={() => this.insideClick()}
underlayColor = '#ddd'
style = {styles.container}
>
<Text style={styles.welcome}>{mainText}</Text>
</TouchableHighlight>
);
}
insideClick(){
alert("類中的方法");
}
}
command+R刷新,點(diǎn)擊屏幕效果圖如下:
箭頭函數(shù)(Arrow functions):
沒(méi)接觸過(guò)JS的同學(xué)可能會(huì)對(duì)
onPress={() => this.insideClick()}
這一行感到很奇怪,其實(shí)這里onPress是一個(gè)函數(shù)類型(在JS中,函數(shù)本身也是一種類型)。這其實(shí)是JS中的箭頭函數(shù),它提供了一種更簡(jiǎn)潔的函數(shù)表達(dá)方式
修改insideClick方法里面的內(nèi)容如下:
insideClick(){
var a = [
"Hydrogen",
"Helium",
"Lithium",
"Beryl-lium"
];
var a2 = a.map(function(s){ return s.length });
var a3 = a.map( (s) => s.length );
console.log(a2);
console.log(a3);
}
然后,commnad+R刷新,可以看到兩個(gè)log的內(nèi)容是一樣的。也就是說(shuō),(s)用來(lái)描述參數(shù),=>后的表示方法的執(zhí)行體。如果學(xué)過(guò)Swift的話,會(huì)發(fā)現(xiàn)和Swift的閉包很像。
數(shù)組:
可以由以下三種方式創(chuàng)建數(shù)組,訪問(wèn)數(shù)組的方式還是通過(guò)角標(biāo)來(lái)訪訪問(wèn):
var a = ["1","2","3","4"];
var b = new Array("1","2","3","4")
var c = Array("1","2","3","4")
console.log(a[1])
數(shù)組有一些方便的方法,例如合并,排序,檢索等,可以在MDN上找到
字典Maps:
var map = {"key1":"value1","key2":"value2"}
var map = {"key1":"value1","key2":"value2"}
map["key4"] = "value4"
console.log(map["key1"])
console.log(map["key4"])
對(duì)象:
JS中的對(duì)象的屬性可以不先聲明,而在運(yùn)行時(shí)候動(dòng)態(tài)添加,例如
var obj = new Object()
obj.name = "1234"
console.log(obj.name)
所以,在React Native中,寫代碼的時(shí)候,存儲(chǔ)數(shù)據(jù)直接this.propertyName =即可。
這里推薦一個(gè)不錯(cuò)的JavaScript教程。
React Native之Flex布局
Flex又叫彈性布局,會(huì)把當(dāng)前組件看做一個(gè)容器,所有子組件都是它容器中的成員,通過(guò)Flex,就能迅速的布局容器中的成員。
使用場(chǎng)景:當(dāng)想快速布局一個(gè)組件中所有子組件的時(shí)候,可以使用Flex布局。
Flex主軸和側(cè)軸:
- Flex中有兩個(gè)主要的概念:主軸和側(cè)軸。
- 主軸與側(cè)軸的關(guān)系:相互垂直的。
主軸:決定容器中子組件默認(rèn)的布局方向:水平,垂直。
側(cè)軸:決定容器中子組件與主軸垂直的布局方向。
如果主軸選擇的是水平方向,那么子組件默認(rèn)就是水平布局排布,側(cè)軸就是控制子組件在垂直方向的布局。
flexDirection屬性:
- flexDirection:決定主軸的方向,水平或者垂直,這樣子組件就會(huì)水平排布或者垂直排布。
- flexDirection共有四個(gè)值,在RN中默認(rèn)為column。
row:主軸為水平方向,從左向右。依次排列
row-reverse:主軸為水平方向,從右向左依次排列
column:主軸為垂直方向,默認(rèn)的排列方式,從上向下排列
column-reverse:主軸為垂直方向,從下向上排列
flexWrap屬性:
- flexWrap:決定子控件在父視圖內(nèi)是否允許多行排列。
- flexWrap共有兩個(gè)值,默認(rèn)為nowrap。
nowrap:組件只排列在一行上,可能導(dǎo)致溢出。
wrap:組件在一行排列不下時(shí),就進(jìn)行多行排列
justifyContent:
- justifyContent:決定子組件在主軸中具體布局,是靠左,還是居中等。
- justifyContent:共有五個(gè)值,默認(rèn)為flex-start。
flex-start:子組件向主軸起點(diǎn)對(duì)齊,如果主軸水平,從左開始,主軸垂直,從上開始。
flex-end:子組件向主軸終點(diǎn)對(duì)齊,如果主軸水平,從右開始,主軸垂直,從下開始。
center:居中顯示,注意:并不是讓某一個(gè)子組件居中,而是整體有居中效果
space-between:均勻分配,相鄰元素間距離相同。每行第一個(gè)組件與行首對(duì)齊,每行最后一個(gè)組件與行尾對(duì)齊。
space-around:均勻分配,相鄰元素間距離相同。每行第一個(gè)組件到行首的距離和每行最后一個(gè)組件到行尾的距離將會(huì)是相鄰元素之間距離的一半
alignItems:
- alignItems:決定子組件在測(cè)軸中具體布局。
- alignItems共有四個(gè)值,默認(rèn)為stretch。
flex-start:子組件向側(cè)軸起點(diǎn)對(duì)齊。
flex-end:子組件向側(cè)軸終點(diǎn)對(duì)齊。
center:子組件在側(cè)軸居中。
stretch:子組件在側(cè)軸方向被拉伸到與容器相同的高度或?qū)挾取?
如果側(cè)軸垂直,決定子組件在上,還是下,或者居中。
alignSelf:
- alignSelf:自定義自己的側(cè)軸布局,用于一個(gè)子組件設(shè)置。
- alignSelf共有五個(gè)值,默認(rèn)為auto。
auto:繼承它的父容器的alignItems屬性。如果沒(méi)有父容器則為 "stretch"
flex-start:子組件向側(cè)軸起點(diǎn)對(duì)齊。
flex-end:子組件向側(cè)軸終點(diǎn)對(duì)齊。
center:子組件在側(cè)軸居中。
stretch:子組件在側(cè)軸方向被拉伸到與容器相同的高度或?qū)挾取?
當(dāng)某個(gè)子組件不想?yún)⒄漳J(rèn)的alignItems時(shí),可以設(shè)置alignSelf,自定義自己的側(cè)軸布局。
flex屬性:
- flex: 決定子控件在主軸中占據(jù)幾等分。
- flex: 任意數(shù)字,所有子控件flex相加,自己flex占總共多少,就有多少寬度.
想要看詳細(xì)的代碼加圖片講解戳這里React Native之Flex布局
ReactNative之CSS布局
ReactNative支持CSS中的布局屬性,因此可以使用CSS布局屬性
CSS顏色大全,下面會(huì)用到,點(diǎn)擊這CSS顏色代碼大全
視圖邊框:
- 設(shè)置自己周邊邊框。
- 注意點(diǎn):一定要設(shè)置邊框?qū)挾取?/li>
borderBottomWidth number 底部邊框?qū)挾?borderLeftWidth number 左邊框?qū)挾?borderRightWidth number 右邊框?qū)挾?borderTopWidth number 頂部邊框?qū)挾?borderWidth number 邊框?qū)挾?border<Bottom|Left|Right|Top>Color 各方向邊框的顏色,<>表示連著一起,例如borderBottomColor
borderColor 所有邊框顏色
尺寸:
width number 寬度
height number 高度
外邊距:
- 設(shè)置組件與組件之間的間距。
- 設(shè)置自己在父控件的位置。
margin number 外邊距
marginBottom number 下外邊距
marginHorizontal number 左右外邊距
marginLeft number 左外邊距
marginRight number 右外邊距
marginTop number 上外邊距
marginVertical number 上下外邊距
注意:
第一個(gè)組件比較特殊,參照父組件,與父控件之間的間距。
其他組件間距,相對(duì)于上一個(gè)組件。
marginRight和width沖突,如果設(shè)置了width,marginRight無(wú)效。
內(nèi)邊距:
- 設(shè)置子控件與當(dāng)前控件的位置。
- 設(shè)置自己的子控件相對(duì)自己的位置。
padding number 內(nèi)邊距
paddingBottom number 下內(nèi)邊距
paddingHorizontal number 左右內(nèi)邊距
paddingLeft number 做內(nèi)邊距
paddingRight number 右內(nèi)邊距
paddingTop number 上內(nèi)邊距
paddingVertical number 上下內(nèi)邊距
相對(duì)定位和絕對(duì)定位:
- 邊緣
left number 左邊緣。
right number 右邊緣。
top number 頂部邊緣。
bottom number 底部邊緣。
- 定位(position):
absolute:絕對(duì)定位,參照父控件位置定位。
relative:相對(duì)定位,參照當(dāng)前控件原始位置定位。
"left", "top", "right" 以及 "bottom" 邊緣屬性進(jìn)行定位。
- 當(dāng)想把一個(gè)已經(jīng)設(shè)置了寬度的控件快速的放在左下角/右下角的時(shí)候,可以使用絕對(duì)定位。
- 當(dāng)想相對(duì)自己做出一些改變的時(shí)候,采用相對(duì)定位,比如相對(duì)自己,往下移動(dòng)一點(diǎn)。
想要看詳細(xì)的代碼加圖片講解戳這里React Native之CSS布局
React的基礎(chǔ)知識(shí)
React:
- React是整個(gè)React框架的入口
React.Component:
- Component是React類的基類,類似于iOS的UIView和Android的View,React和React native都定義了很多方便的子類來(lái)給開發(fā)者使用。
Component 相關(guān)對(duì)象方法:
- render這個(gè)函數(shù)返回一個(gè)根的視圖,用來(lái)渲染實(shí)際的Component可視部分,如下:
render() {
return (
<TouchableHighlight
onPress={() => this.insideClick()}
underlayColor = '#ddd'
style = {styles.container}
>
<Text style={styles.welcome}>{mainText}</Text>
</TouchableHighlight>
);
}
生命周期:
export default class CJFirstRN extends Component {
// 1.構(gòu)造方法
constructor(props){
super(props)
}
// 2.即將加載組件的方法
componentWillMount() {
// 在最初的渲染之前調(diào)用一次,在React中,設(shè)置this.state會(huì)導(dǎo)致重新渲染
// 但是componentWillMount中設(shè)置this.state并不會(huì)對(duì)導(dǎo)致render調(diào)用多次
console.log('componentWillMount')
}
// 3.render()去渲染組件
render() {
return (
<View style={styles.container}>
</View>
);
}
// 4.加載組件完成的方法
componentDidMount() {
// 在渲染結(jié)束后,調(diào)用一次
console.log('componentDidMount')
}
// 5.0接受到新傳入的props值
componentWillReceiveProps() {
// 在component接收到新的參數(shù)前調(diào)用,在這個(gè)方法中調(diào)用this.setState不會(huì)觸發(fā)二次渲染,而且第一次渲染的時(shí)候不會(huì)調(diào)用這個(gè)方法
console.log('componentWillReceiveProps')
}
// 5.1是否刷新頁(yè)面
shouldComponentUpdate() {
// 在每次重新觸發(fā)渲染之前調(diào)用,可以在這個(gè)方法中返回false來(lái)取消本次渲染。
console.log('shouldComponentUpdate')
return true
}
// 6.即將刷新頁(yè)面
componentWillUpdate(){
// 在重新渲染之前調(diào)用
// Warning:這個(gè)方法里不能調(diào)用this.setState(),否則會(huì)陷入死循環(huán)
console.log('componentWillUpdate')
}
// 7.完成刷新頁(yè)面的動(dòng)作
componentDidUpdate() {
console.log('componentDidUpdate')
}
// 8.組件銷毀的時(shí)候調(diào)用
componentWillUnmount() {
console.log('componentWillUnmount')
}
}
推薦一些RN學(xué)習(xí)資料:
RN的插件庫(kù)
React Native 從入門到原理
React-Native學(xué)習(xí)指南
ReactNative快速入門筆記
React/React Native 的ES5 ES6寫法對(duì)照表
React Native布局詳細(xì)指南
React Native專題
Flux 架構(gòu)入門教程