React Native 极快速入门

整理了一下关于 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开发要学习些什么呢?

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

下面这张图内是项目的所有内容:


目录结构.jpeg
绿色框内的两个文件 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刷新,效果图如下:


效果图.jpeg

常量可以看到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)

控制图如下:

控制图.png

函数:

函数的定义如下,由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刷新,点击屏幕效果图如下:


哈哈哈.jpeg

这样的方法是定义在全局的,当在类中定义的时候,不需要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刷新,点击屏幕效果图如下:


类中的方法.jpeg

箭头函数(Arrow functions):

没接触过JS的同学可能会对

onPress={() => this.insideClick()}

这一行感到很奇怪,其实这里onPress是一个函数类型(在JS中,函数本身也是一种类型)。这其实是JS中的箭头函数,它提供了一种更简洁的函数表达方式
修改insideClick方法里面的内容如下:

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刷新,可以看到两个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 架构入门教程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342