整理了一下关于 React Native 入门内容,仅供参考,如有问题,还请指出。
React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的UI框架 React 在原生移动应用平台的衍生产物,目前支持iOS和安卓两大平台。RN使用Javascript语言,类似于HTML的JSX,以及CSS来开发移动应用,因此熟悉Web前端开发的技术人员只需很少的学习就可以进入移动应用开发领域。
React Native使你能够在Javascript和React的基础上获得完全一致的开发体验,构建世界一流的原生APP。
React Native着力于提高多平台开发的开发效率 —— 仅需学习一次,编写任何平台。(Learn once, write anywhere)。
Facebook已经在多项产品中使用了React Native,并且将持续地投入建设React Native。
React Native主要特性如下:
- 原生的iOS组件
React Native主张“Learn once, write everywhere”而非其他跨平台工具一直宣扬的“Write once, run everywhere”。通过React Native,开发者可以使用UITabBar、UINavigationController等标准的iOS平台组件,让应用界面在其他平台上亦能保持始终如一的外观、风格。
- 异步执行
JavaScript应用代码和原生平台之间所有的操作都采用异步执行模式,原生模块使用额外线程,开发者可以解码主线程图像、后台保存至磁盘、无须顾忌UI等诸多因素直接度量文本设计布局。
- 触摸处理
React Native引入了一个类似于iOS上Responder Chain响应链事件处理机制的响应体系,并基于此为开发者提供了诸如TouchableHighlight等更高级的组件。
要学好React Native开发要学习些什么呢?
- Html+CSS+JavaScript的基本功肯定是少不了;
- Node.js的基本概念学习。API文档:https://nodejs.org/dist/v4.2.2/docs/api/
- JSX: JavaScript语法的一个扩展,类似XML结构。https://facebook.github.io/react/docs/jsx-in-depth.html
- FLUX: Facebook公司的一个创建用户客户端web程序的框架。https://facebook.github.io/flux/docs/overview.html
React Native文档:
系统环境配置:
初始化项目:
首先创建一个项目:
cd /Users/cj/Desktop/RN
react-native init CJFirstRN
CJFirstRN 是项目名,该命令会创建一个名为 CJFirstRN 的文件夹,其中是一些依赖包,入口文件,项目工程文件等
稍等一会...
初始化项目完成之后,你可以选择两种不同的方式运行 App 在 iOS/Android 平台:
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
下面这张图内是项目的所有内容:
绿色框内的两个文件 index.ios.js/index.android.js 对应的是 iOS/Android 的入口文件;
node_modules文件夹里是依赖包;
ios、android文件夹中是各自的工程文件;
package.json类似于 iOS 内的podfile;
app.json是项目的一些配置信息。
以 iOS 为例,打开 index.ios.js 文件,查看一些模板代码,下面是代码和他们的意思:
/*
第一部分
导入React Native包,导入React Native组件
AppRegistry:JS运行所有React Native应用的入口
StyleSheet:React Native中使用的样式表,类似CSS样式表
各种开发中需要使用的组件
模板中使用的是ES6语法,ES5语法如下
let React = require("react-native");
let {
AppRegistry,
StyleSheet,
Text,
View
} = React
require函数,搜索目录加载文件
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
/*
第二部分
创建React Native组件
这是默认的载入类,继承自Component,Component类似于Android-View和iOS-UIView
当一个组件要显示的时候,会自动调用render()去渲染组件
模板中使用的是ES6语法,
render(){}是ES6的函数简写
ES5语法如下:
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创建样式实例
在应用中只会创建一次,不用每次在渲染周期中重新创建
*/
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,
},
});
/*
第四部分
注册入口组件
AppRegistry:负责注册运行React Native应用程序的JavaScript入口
registerComponent注册应用程序的入口组件。告知React Native哪一个组件被注册为应用的根容器
第一个是模块名称,类似于"key",和 iOS AppDelegate 里面的一样,Android的我没看ㄟ( ▔, ▔ )ㄏ
第二个参数使用了ES6语法,箭头函数:
() => HelloWorld
=> 左边是函数参数,右边是函数返回值
返回的必须是定义的组件类的名字
等价于
function() {
return HelloWorld
}
*/
AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
看到这,你应该也明白了各个模块的作用,接下来我们来了解一些 React Native 开发基础。
React Native 开发基础
什么是JavaScript?
JS是一个轻量级的,解释型的讲函数视为一级公民的程序设计语言。它是一种基于原型的多范式动态脚本语言,支持面向对象,命令式编程和函数式编程。
JavaScript的标准是 ECMAScript,React Native的语法是基于ECMAScript 6,简称ES6。
声明:
- var 声明变量,可以在声明的时候初始化为一个,可以修改,如果不初始化会输出undefined,不会报错。
- let 声明块范围局部变量,可以在声明的时候初始化一个值,函数内部使用let定义后,对函数外部无影响。
- const 声明一个只读常量,不可以修改,而且必须初始化。
Tips:JS是大小写敏感的。
变量、常量:
- 命名要以数字字母下划线开头
Tips:JS是一个动态类型语言(dynamically typed language)中,所以变量不需声明类型,必要的时候自动转换。
例如,在 class HelloWorld上 添加两行
var mainText = "我真帅"
var subText = "嗯,没毛病!"
然后,让Text来显示这个这两个变量
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({
...
});
就是一个常量,记住在声明的时候,必须初始化。
数据结构和类型:
- 六种基本的原型数据类型
Boolean:布尔值,true或者false
null:一个表明null的特殊关键字,注意JS中大小写敏感,null和NULL是完全不同的东西
undefined:属性未定义的变量
Number:数字
String:字符串
Symbol :ES6中新增的,唯一不可变的
- 以及Object类型
流程控制:
if,else
switch
for
while
break
continue
这个各个语言大同小异,不浪费篇幅了,有一点要提一下,JS中的Switch Case中可以是String。
有一点要注意,以下值在JS中是会识别为false:
false
undefined
null
0
NaN
空字符串 ("")
注释:
// 这是一个单行注释。
/* 这是一个多行注释。它可以是任意长度,你可以在这里随便写什么。 */
Promises:
- 从ES6开始,JS中引入了Promises来处理异步和延迟操作,在React Native的网络请求中是很常见的。
- 一个promise有以下几种状态
pending:最初的状态
fulfilled:执行失败
rejected:执行成功
settled:执行结束了,失败(rejected)或者成功(fulfilled)
控制图如下:
函数:
函数的定义如下,由function关键字声明,在()添加输入,输入不需要声明类型
function globalFunc(str){
alert(str);
}
我们接着上述的工程,添加一个可点击的TouchableHighLight
。
在 import 中,添加一行TouchableHighlight
,然后重新定义变量和类的内容:
var mainText = "点击屏幕任意位置"
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刷新,点击屏幕效果图如下:
这样的方法是定义在全局的,当在类中定义的时候,不需要funciton关键字。
在类中定义通过this.functionName来访问:
var mainText = "点击屏幕任意位置"
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刷新,点击屏幕效果图如下:
箭头函数(Arrow functions):
没接触过JS的同学可能会对
onPress={() => this.insideClick()}
这一行感到很奇怪,其实这里onPress是一个函数类型(在JS中,函数本身也是一种类型)。这其实是JS中的箭头函数,它提供了一种更简洁的函数表达方式
修改insideClick方法里面的内容如下:
insideClick(){
var a = [
"Hydrogen",
"Helium",
"Lithium",
"Beryllium"
];
var a2 = a.map(function(s){ return s.length });
var a3 = a.map( (s) => s.length );
console.log(a2);
console.log(a3);
}
然后,commnad+R刷新,可以看到两个log的内容是一样的。也就是说,(s)用来描述参数,=>后的表示方法的执行体。如果学过Swift的话,会发现和Swift的闭包很像。
数组:
可以由以下三种方式创建数组,访问数组的方式还是通过角标来访访问:
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])
数组有一些方便的方法,例如合并,排序,检索等,可以在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"])
对象:
JS中的对象的属性可以不先声明,而在运行时候动态添加,例如
var obj = new Object()
obj.name = "1234"
console.log(obj.name)
所以,在React Native中,写代码的时候,存储数据直接this.propertyName =即可。
这里推荐一个不错的JavaScript教程。
React Native之Flex布局
Flex又叫弹性布局,会把当前组件看做一个容器,所有子组件都是它容器中的成员,通过Flex,就能迅速的布局容器中的成员。
使用场景:当想快速布局一个组件中所有子组件的时候,可以使用Flex布局。
Flex主轴和侧轴:
- Flex中有两个主要的概念:主轴和侧轴。
- 主轴与侧轴的关系:相互垂直的。
主轴:决定容器中子组件默认的布局方向:水平,垂直。
侧轴:决定容器中子组件与主轴垂直的布局方向。
如果主轴选择的是水平方向,那么子组件默认就是水平布局排布,侧轴就是控制子组件在垂直方向的布局。
flexDirection属性:
- flexDirection:决定主轴的方向,水平或者垂直,这样子组件就会水平排布或者垂直排布。
- flexDirection共有四个值,在RN中默认为column。
row:主轴为水平方向,从左向右。依次排列
row-reverse:主轴为水平方向,从右向左依次排列
column:主轴为垂直方向,默认的排列方式,从上向下排列
column-reverse:主轴为垂直方向,从下向上排列
flexWrap属性:
- flexWrap:决定子控件在父视图内是否允许多行排列。
- flexWrap共有两个值,默认为nowrap。
nowrap:组件只排列在一行上,可能导致溢出。
wrap:组件在一行排列不下时,就进行多行排列
justifyContent:
- justifyContent:决定子组件在主轴中具体布局,是靠左,还是居中等。
- justifyContent:共有五个值,默认为flex-start。
flex-start:子组件向主轴起点对齐,如果主轴水平,从左开始,主轴垂直,从上开始。
flex-end:子组件向主轴终点对齐,如果主轴水平,从右开始,主轴垂直,从下开始。
center:居中显示,注意:并不是让某一个子组件居中,而是整体有居中效果
space-between:均匀分配,相邻元素间距离相同。每行第一个组件与行首对齐,每行最后一个组件与行尾对齐。
space-around:均匀分配,相邻元素间距离相同。每行第一个组件到行首的距离和每行最后一个组件到行尾的距离将会是相邻元素之间距离的一半
alignItems:
- alignItems:决定子组件在测轴中具体布局。
- alignItems共有四个值,默认为stretch。
flex-start:子组件向侧轴起点对齐。
flex-end:子组件向侧轴终点对齐。
center:子组件在侧轴居中。
stretch:子组件在侧轴方向被拉伸到与容器相同的高度或宽度。
如果侧轴垂直,决定子组件在上,还是下,或者居中。
alignSelf:
- alignSelf:自定义自己的侧轴布局,用于一个子组件设置。
- alignSelf共有五个值,默认为auto。
auto:继承它的父容器的alignItems属性。如果没有父容器则为 "stretch"
flex-start:子组件向侧轴起点对齐。
flex-end:子组件向侧轴终点对齐。
center:子组件在侧轴居中。
stretch:子组件在侧轴方向被拉伸到与容器相同的高度或宽度。
当某个子组件不想参照默认的alignItems时,可以设置alignSelf,自定义自己的侧轴布局。
flex属性:
- flex: 决定子控件在主轴中占据几等分。
- flex: 任意数字,所有子控件flex相加,自己flex占总共多少,就有多少宽度.
想要看详细的代码加图片讲解戳这里React Native之Flex布局
ReactNative之CSS布局
ReactNative支持CSS中的布局属性,因此可以使用CSS布局属性
CSS颜色大全,下面会用到,点击这CSS颜色代码大全
视图边框:
- 设置自己周边边框。
- 注意点:一定要设置边框宽度。
borderBottomWidth number 底部边框宽度
borderLeftWidth number 左边框宽度
borderRightWidth number 右边框宽度
borderTopWidth number 顶部边框宽度
borderWidth number 边框宽度
border<Bottom|Left|Right|Top>Color 各方向边框的颜色,<>表示连着一起,例如borderBottomColor
borderColor 所有边框颜色
尺寸:
width number 宽度
height number 高度
外边距:
- 设置组件与组件之间的间距。
- 设置自己在父控件的位置。
margin number 外边距
marginBottom number 下外边距
marginHorizontal number 左右外边距
marginLeft number 左外边距
marginRight number 右外边距
marginTop number 上外边距
marginVertical number 上下外边距
注意:
第一个组件比较特殊,参照父组件,与父控件之间的间距。
其他组件间距,相对于上一个组件。
marginRight和width冲突,如果设置了width,marginRight无效。
内边距:
- 设置子控件与当前控件的位置。
- 设置自己的子控件相对自己的位置。
padding number 内边距
paddingBottom number 下内边距
paddingHorizontal number 左右内边距
paddingLeft number 做内边距
paddingRight number 右内边距
paddingTop number 上内边距
paddingVertical number 上下内边距
相对定位和绝对定位:
- 边缘
left number 左边缘。
right number 右边缘。
top number 顶部边缘。
bottom number 底部边缘。
- 定位(position):
absolute:绝对定位,参照父控件位置定位。
relative:相对定位,参照当前控件原始位置定位。
"left", "top", "right" 以及 "bottom" 边缘属性进行定位。
- 当想把一个已经设置了宽度的控件快速的放在左下角/右下角的时候,可以使用绝对定位。
- 当想相对自己做出一些改变的时候,采用相对定位,比如相对自己,往下移动一点。
想要看详细的代码加图片讲解戳这里React Native之CSS布局
React的基础知识
React:
- React是整个React框架的入口
React.Component:
- Component是React类的基类,类似于iOS的UIView和Android的View,React和React native都定义了很多方便的子类来给开发者使用。
Component 相关对象方法:
- render这个函数返回一个根的视图,用来渲染实际的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.构造方法
constructor(props){
super(props)
}
// 2.即将加载组件的方法
componentWillMount() {
// 在最初的渲染之前调用一次,在React中,设置this.state会导致重新渲染
// 但是componentWillMount中设置this.state并不会对导致render调用多次
console.log('componentWillMount')
}
// 3.render()去渲染组件
render() {
return (
<View style={styles.container}>
</View>
);
}
// 4.加载组件完成的方法
componentDidMount() {
// 在渲染结束后,调用一次
console.log('componentDidMount')
}
// 5.0接受到新传入的props值
componentWillReceiveProps() {
// 在component接收到新的参数前调用,在这个方法中调用this.setState不会触发二次渲染,而且第一次渲染的时候不会调用这个方法
console.log('componentWillReceiveProps')
}
// 5.1是否刷新页面
shouldComponentUpdate() {
// 在每次重新触发渲染之前调用,可以在这个方法中返回false来取消本次渲染。
console.log('shouldComponentUpdate')
return true
}
// 6.即将刷新页面
componentWillUpdate(){
// 在重新渲染之前调用
// Warning:这个方法里不能调用this.setState(),否则会陷入死循环
console.log('componentWillUpdate')
}
// 7.完成刷新页面的动作
componentDidUpdate() {
console.log('componentDidUpdate')
}
// 8.组件销毁的时候调用
componentWillUnmount() {
console.log('componentWillUnmount')
}
}
推荐一些RN学习资料:
RN的插件库
React Native 从入门到原理
React-Native学习指南
ReactNative快速入门笔记
React/React Native 的ES5 ES6写法对照表
React Native布局详细指南
React Native专题
Flux 架构入门教程