React native 基本开发指南

1.项目,组件(Component)的基本结构
2.Component的生命周期
3.界面布局
4.基本网络请求Fetch
5.第三方库的使用
6.基本数据存储方式
7.如何使用原生UI控件(Android)
8.与原生项目交互的四种方式(Android)

项目地址:点这里
1.导出项目
2.在项目根目录输入npm install命令
3.输入react-native run-android 在android设备上运行

后续会继续完善包括:
1.如何打包,
2.如何进行热更新
3.性能问题
4.使用FISH框架
5.开发一个完整的项目

在RN世界里,Component(组件)相当于一个UI控件,APP就是由各种Component组合在一起显示出来的。一开始我对这句话不是很理解,但是随着我对RN的一步步了解,对这句话的体会也越深刻。
前提:了解JS,Html,CSS
可以阅读把阮一峰老师的《 ECMAScript 6 入门》这篇关于ES6的文档
其中关于Promise对象,Async函数等都比较重要,像网络请求,数据存储都需要用到异步操作。

一、项目结构

新建一个RN项目,目录大致如下:

(1)package.json:项目基本信息还有依赖的第三方库的信息

(2)index.js,主要用来注册启动组件,即应用打开后的第一个界面

(3)android,ios文件夹,自动生成对应平台的代码

(4)node_modules导入的依赖库文件

二、component(组件)的基本结构

(1)组件导入区:所有使用的组件都必须先导入,否则会直接报错。

(2)组件具体展示:render方法返回具体的显示界面

(3)组件样式:自定义样式

运行结果如下:

还有一些RN比较重要的概念

Props(属性):在组件使用时调用,组件生命周期中不可改变。

这里以Text举例,Text组件拥有width和height属性,父组件在使用时可以为Text的属性进行赋值。这里RN可以自定义组件,设置一些属性提供给父组件调用。

运行结果如下:

State(状态):组件生命中可以改变,常用来动态展示数据,

通过this.setState方法改变state值从而使组件重新加载,一般在组件的构造函数中进行初始化。

运行结果如下:

三、component(组件)的生命周期

当应用启动,React Native在内存中维护着一个虚拟DOM,组件的生命周期就是指组件初始化并挂载到虚拟DOM为起始,到组件从虚拟DOM卸载为终结。生命周期的方法就是组件在虚拟DOM中不同状态的描述。

从上图所示,组件的生命周期分为三个阶段,分别是挂载(mounting)、更新(updating)和卸载(Unmounting),其中挂载和更新阶段都会调用rander方法进行绘制。下面对这三个阶段分别进行讲解。

1、挂载

挂载指的是组件的实例被创建并插入到DOM中,挂载会调用如下方法。

(1)constructor

constructor是RN组件的构造方法,它在RN组件被加载前先被调用。当我们的组件继承自React.Component时,需要在构造方法中最先调用super(props)。如果不需要初始化state,则不需要实现构造方法。
在构造方法中初始化state,如下所示。

(2)componentWillMount

componentWillMount方法在挂载前被立即调用。它在render方法前被执行,因此,在componentWillMount方法中设置state并不会导致重新被渲染。它只会被执行一次,通常情况下,建议使用constructor方法来代替它。

(3)render

该方法是必须的,一旦调用,则会去检查 this.props 和 this.state 的数据并返回一个 React 元素。render方法中不应该修改组件的props和state,因为render方法是“纯洁的”,这意味着每次调用该方法时都会返回相同的结果。render方法在更新阶段也会被调用,前提是shouldComponentUpdate方法返回true。
同时,每次调用this.setState方法之后都会重新调用render方法对组件进行重新加载。

(4)componentDidMount

componentDidMount方法在组件被挂载后立即调用,在render方法后被执行。开发者可以在这个方法中获取其中的元素或者子组件,需要注意的是,子组件的componentDidMount方法会在父组件的componentDidMount方法之前调用。如果需要从网络加载数据显示到界面上,在这里进行网络请求是一个不错的选择。在componentDidMount方法中设置state将会被重新渲染。

2、更新

改变props或者state时可以导致更新,当一个组件被重新渲染时,会调用如下方法。

(1)componentWillReceiveProps

componentWillReceiveProps方法会在挂载的组件接收到新的props时被调用,它接收一个Object类型参数nextProps,表示新的props。通常在这个方法中接收新的props值,并根据props的变化,通过调用 this.setState() 来更新组件state,this.setState()不会触发 render方法的调用。
在挂载的过程中,初始的props并不会触发调用componentWillReceiveProps方法,这个方法只会在组件中的props更新时被调用,另外,调用this.setState()也不会触发调用componentWillReceiveProps方法。

(2)shouldComponentUpdate

当组件接收到新的props和state时,shouldComponentUpdate方法被调用,它接收两个Object参数,nextProps是新的props,nextState是新的state。
shouldComponentUpdate方法默认返回true,用来保证数据变化时,组件能够重新渲染。你也可以重载这个方法,通过检查变化前后props和state,来决定组件是否需要重新渲染。如果返回false,则组件不会被重新渲染,也不会调用本方法后面的componentWillUpdate和componentDidUpdate方法。

(3)componentWillUpdate

如果组件props或者state改变,并且此前的shouldComponentUpdate方法返回为 true,则会调用该方法。componentWillUpdate方法会在组件重新渲染前被调用,因此,可以在这个方法中为重新渲染做一些准备工作。需要注意的是,在这个方法中,不能使用 this.setState 来更改state,如果想要根据props来更改state,需要在componentWillReceiveProps方法中去实现,而不是在这里。

(4)componentDidUpdate

组件重新渲染完成后会调用componentDidUpdate方法。两个参数分别是渲染前的props和渲染前的state。这个方法也适合写网络请求,比如可以将当前的props和prevProps进行对比,发生变化则请求网络。

3、卸载

卸载就是从DOM中删除组件,会调用如下方法。

(1)componentWillUnmount()

componentWillUnmount方法在组件卸载和销毁之前被立即调用。可以在这个方法中执行必要的清理工作,比如,关掉计时器、取消网络请求、清除组件装载中创建的DOM元素等等。

四、界面布局

界面布局是很重要的一个环节,毕竟一个应用要长得“好看”才能留下更多的用户,这里React Native已经提供了很多基本组件,可以在React Native中文网的文档中查看。还有GitHub中也有人开发第三方组件库,包括FISH-X组件库都很大程度上方便了我们对布局的使用,之后也会介绍如何导入第三方库。
关于布局这块内容,我本身也在学习,这里提供几个关于前端布局的基础使用。
《Flex 布局教程:语法篇》——阮一峰
《Flex 布局教程:实例篇》——阮一峰
《React-Native 的基本控件属性方法》——冬瓜小生

五、基本网络请求Fetch

在使用前可以先了解一些基本概念:
为什么使用 Fetch《传统 Ajax 已死,Fetch 永生》——Cam
《使用 Fetch 先了解一下 Promise 概念》——来自 MDN 社区
《React Native网络请求及 UI 展示》——王方帅

基本使用:
注意:初始数据的获取一般在componentDidMount这个方法中进行

运行结果:

六、第三方库的使用

RN拥有很多优秀的第三方库,使用一些成熟的轮子能让我们更快的搭建出一个常用app的框架。
第三方库的使用简单来说只有两步:

(1)导入第三方库:在工程目录下输入命令:npm install [第三方库] –save

导入成功后,packge.json文件里面会有对应第三方库的信息

(2)按照描述使用第三方库,以下是几个基本例子

react-native-tab-navigator (使用较简单) 更适合作为底部的 tab,使用方式也超级简单

react-native-swiper,banner类

react-native-scrollable-tab-view (star 最多的 tab 类控件) 更适合作为顶部的 tab,类似今日头条中的效果

还有FISH-X组件库的集成,之前文档中已经介绍,这里就不重复描述了。

七、RN的数据存储

RN使用AsyncStorage将数据存储到本地,AsyncStorage是一个基于key-value键值对的异步持久化存储系统,对于应用来说其存储的内容全局生效。如果有开发过Andorid的人来说AsyncStorage和Sharedpreferences是十分类似的。
这里提供官网的介绍和使用教程
AsyncStorage使用异步Promise模式存储数据,例如调用存储方法存储一个字符串setItem(‘I_AM_KEY’,’i_am_value’),setItem会异步执行,等setItem执行完成后会返回一个Promise对象。这里强烈建议先了解Promise,async等基本概念,在本篇文章的最开始就给出了参考教程。
基本使用:

操作步骤:

(1)setItem

(2)getItem

(3)moveItem

(4)getItem

当然数据存储不止AsyncStorage一种,也可以使用sqlite,可以参考react-native-sqlite。(由于还没尝试所以暂时没有记录)
甚至可以用RN调用原生的方法进行存储,这里之后会介绍如何与原生进行交互。

八、使用原生UI组件

比如在Android自定义了一个控件想显示在RN的界面上,这个是可以实现的。RN提供了调用原生UI组件的方法,令布局的使用更加的灵活。
这里以封装Android原生控件为例
Android端:

(1)自定义一个View,或者直接使用Android原生的控件

(2)创建一个ViewManager:

getName方法:返回组件的名字提供给RN进行调用
createViewInstance方法:返回自定义的View
@ReactProp注解:提供给RN设置的属性

要导出给JavaScript使用的属性,需要申明带有@ReactProp(或@ReactPropGroup)注解的设置方法。方法的第一个参数是要修改属性的视图实例,第二个参数是要设置的属性值。方法的返回值类型必须为void,而且访问控制必须被声明为public。JavaScript所得知的属性类型会由该方法第二个参数的类型来自动决定。支持的类型有:boolean, int, float, double, String, Boolean, Integer, ReadableArray, ReadableMap。@ReactProp注解必须包含一个字符串类型的参数name。这个参数指定了对应属性在JavaScript端的名字。除了name,@ReactProp注解还接受这些可选的参数:defaultBoolean, defaultInt, defaultFloat。

(3)创建一个ReactPackage

createViewManagers:返回自定义ViewManager的集合
createNativeModules:返回自定义NativeModule的集合(这个之后将通信的时候会用到)

(4)在Application中对我们创建的ReactPackage进行注入

如果本身是RN直接生成的Android代码,则已经有了这个Application,如果是Android导入RN就需要自己进行添加
RN端:

(1)实现js模块调用requireNativeComponent方法

(2)在JS中使用原生的View

运行结果如下:

九、RN与原生进行通信

RN与原生App之间的通信有四种方法,接下来让我们一一来了解这些

(1)RCTDeviceEventEmitter 事件方式

(2)Callback 回调方式

(3)Promise

(4)直传常量数据(原生向RN)

四种方式各具不同优缺点

1. RCTDeviceEventEmitter

优点:可任意时刻传递,Native主导控制。

2. Callback

优点:JS调用,Native返回。
缺点:CallBack为异步操作,返回时机不确定

3. Promise

优点:JS调用,Native返回。
缺点:每次使用需要JS调用一次

4. 直传常量数据

优点:调用简单
确定:只能RN调用原生
前三种的方法大致的实现步骤如下:

(1)定义Module类,继承ReactContextBaseJavaModule

     在Module类中,我们定义交互的方法,例如RN调用Native的方法,Native调用RN的方法等。

(2)定义Package类,继承ReactPackage

     实现Package的createNativeModules方法,将Module实例添加到集合。

(3)定义Application,继承ReactApplication

     实现getPackages方法,将Package实例添加到getPackages下的集合。

最后一种方法跨域传值,只能从原生端向RN端传递。RN端可通过 NativeModules.[module名].[参数名] 的方式获取

接下来直接上代码

1. RCTDeviceEventEmitter

Android代码:
创建ReactContextBaseJavaModule

定义Package类,继承ReactPackage

定义Application,这个和第八点的做法一样

RN代码:
使用DeviceEventEmitter添加监听事件,提供原生调用
使用NativeModules.commModule调用原生方法,名字一定要一致

运行结果如下

2. Callback

和上面的差别在于,调用原生方法的同时会传入一个Callback方法进行回调
android代码:
增加调用方法,其他都不需要处理

RN代码:
在调用方法的时候传入Callback进行回调,其他不变

运行结果:

3. Promise

Promise和RN十分类似,只不过将Callback换成了Promise
android代码:

RN代码:

运行结果:

4. 直传常量数据

RN直接调用原生的数据,写法很简单
Android端直接调用getConstants方法

RN使用NativeModules.commModule.Constant获取原生代码中定义的常量

运行结果:

上面的所有代码我都上传到GitHub上了,地址点这里
下载成功后,命令行运行npm install下载modules
react-native run-android直接运行在安卓设备上

参考网址:
react native入门指南
react native Demo大全

更多相关文章

  1. 【 Android(安卓)10 系统启动 】系列 -- Launcher(应用门户)
  2. EventThread线程对VSync的接收
  3. android MediaCodec ACodec OMX tips
  4. Android判断现在所处界面是否为home主桌面的方法
  5. Android获得内/外置存储卡路径的方法
  6. android 获取网络数据,回传到本地用TextView显示乱码问题解决方法
  7. Android进程间通信(二):通过AIDL介绍Binder的工作机制
  8. Android实现ListView异步加载图片的方法
  9. 在android中使用USB进行通信的4种方法

随机推荐

  1. Android(安卓)文件读写操作 总结
  2. [置顶] Android安全机制分析
  3. Android怎么找到最优适配资源
  4. android TextView设置字过多长长度后面显
  5. [Android] Nexus 7 二代连接 Windows 7
  6. live555移植到Android过程.
  7. android studio 开发 Execution failed f
  8. Android应用开发提高系列(5)——Android动
  9. Android(安卓)中级教程之------Android(
  10. Android程序员学IOS-UI篇