移动开发中的React Native研究

关于React Native详细介绍和基本使用, 可以直接参考官方手册, 本文就不重复造轮子了

目录

  • 集成和打包

    • iOS

    • android

  • 数据持久化

    • AsyncStorage

    • NSUserDefaults

    • react-native-sqlite-storage

    • Realm

  • 热补丁

    • CodePush

    • AppHub

    • Siphon

  • 第三方库

    • Redux

    • react-native-material-kit

    • react-native-vector-icons

    • react-native-app-intro

  • 开源应用

    • f8app

    • react-native-nba-app

    • react-weather

    • reading

  • 总结

    • React-Native的优势

    • React-Native的缺点

    • React-Native的比较

集成和打包

重新创建纯的React Native工程的教程和文章有很多, 在此就直接略过了

iOS

如何将React Native集成到Native的工程中, 官网也有介绍Integration With Existing Apps, 这里就不详细解释了

在打包时需要注意的是, 首先使用如下命令将React Native资源打成bundle

react-native bundle --entry-file index.ios.js --platform ios --bundle-output ios/react.bundle

然后打开Xcode, 将react.bundle添加至工程中, 最后和普通的iOS工程一样, 打包发布即可

Demo的完整工程代码, 参考这里的ReactNativeAndNativeDemo

android

和iOS类似, 打包android时, 首先也需要将React Native资源打成bundle

react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/ReactNativeAndNativeDemo/app/src/main/assets/index.android.bundle --assets-dest android/ReactNativeAndNativeDemo/app/src/main/res/

然后, 再打包发布

关于更多android打包, 可以参考React Native发布APP之签名打包APK

数据持久化

AsyncStorage

import { AsyncStorage } from 'react-native';

var keyName = 'key';
var keyValue = '262';
AsyncStorage.setItem(keyName, keyValue, (error) => {
    console.log('' + error);
});

AsyncStorage.getItem(keyName, (error, result) => {
    console.log('' + result);
});

优点

  • react native自带

  • 简单易用

缺点

  • 只能存储字符串

NSUserDefaults

// ReactViewBridgeModule.h
#import 
#import 

@interface ReactViewBridgeModule : NSObject 

@end

// ReactViewBridgeModule.m
#import "ReactViewBridgeModule.h"

@implementation ReactViewBridgeModule

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(setUserDefaults:(NSString *)key value:(NSString *)value) {
    [[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
}

RCT_EXPORT_METHOD(getUserDefaults:(NSString *)key callback:(RCTResponseSenderBlock)callback) {
    NSString *ret = [[NSUserDefaults standardUserDefaults] objectForKey:key];
    NSLog(@"ret = %@", ret);
    if(!ret){
        ret = @"";
    }
    callback(@[ret]);
}

@end
NativeModules.ReactViewBridgeModule.setUserDefaults(keyName, keyValue);

NativeModules.ReactViewBridgeModule.getUserDefaults(keyName, (value) => {
    console.log(value);
});

优点

  • 相比AsyncStorage支持更多的存储数据类型

缺点

  • 需要实现Native与Javascript的通信

  • 依赖于iOS平台

react-native-sqlite-storage

这里使用的是react-native-sqlite-storage, 你也可以在github上参考其他sqlite的实现, 其中详细的安装和配置, 仍然参考react-native-sqlite-storage

import SQLite from 'react-native-sqlite-storage';

// insert operation
var db = SQLite.openDatabase("test.db", "1.0", "Test Database", 200000,
    () => {
        console.log('opened');

        var sql = 'CREATE TABLE IF NOT EXISTS UserTable (FirstName varchar(255), LastName varchar(255))';
        db.transaction((tx) => {
            tx.executeSql(sql, [], (tx, results) => {
                console.log('' + results);
            });
        });

        var insertsql = "INSERT INTO UserTable VALUES ('mu', 'ji')";
        db.transaction((tx) => {
            tx.executeSql(insertsql, [], (tx, results) => {
                console.log('' + results);
            });
        });
    },
    (error) => {
        console.log('open error: ' + error);
    });

// query operation
var db = SQLite.openDatabase("test.db", "1.0", "Test Database", 200000,
    () => {
        console.log('opened');

        var querysql = "SELECT * FROM UserTable";
        db.transaction((tx) => {
            tx.executeSql(querysql, [], (tx, results) => {
                var len = results.rows.length;
                for (let i = 0; i < len; i++) {
                let row = results.rows.item(i);
                    console.log(`User name: ${row.FirstName}, Dept Name: ${row.LastName}`);
                }
            });
        });
    },
    (error) => {
        console.log('open error: ' + error);
    });

Realm

关于Realm的更多介绍可以参考Realm

import Realm from 'realm';

let realm = new Realm({
    schema: [{name: 'Dog', properties: {name: 'string'}}]
});
realm.write(() => {
    realm.create('Dog', {name: 'Rex'});
});

Count of Dogs in Realm: {realm.objects('Dog').length}

安装Realm时, 这条命令是一定要执行的: react-native link relam

热补丁

CodePush

CodePush是由微软出品, 支持React Native和Cordova应用的即时更新

使用非常简单, 基于命令行

  • 发送更新
code-push release <应用名称>  <对应的应用版本> --deploymentName: 更新环境
--description: 更新描述  --mandatory: 是否强制更新

code-push release GitHubPopular ./bundles/index.android.bundle 1.0.6 --deploymentName Production  --description "1.支持文章缓存。" --mandatory true
  • 同步更新
import codePush from 'react-native-code-push'

codePush.sync()

如果可以进行更新, CodePush会在后台静默地将更新下载到本地, 等待APP下一次启动的时候应用更新, 以确保用户看到的是最新版本

如果更新是强制性的, 更新文件下载好之后会立即进行更新

但是CodePush也存在如下问题

  • 服务器在国外, 在国内访问, 网速不是很理想

  • 其升级服务器端程序并不开源的, 后期微软会不会对其收费还是个未知数

  • 不支持增量更新

关于更多CodePush, 可以参考React Native热更新部署/热更新-CodePush最新集成总结

AppHub

AppHub由国外一家公司出品, 支持React Native应用的即时更新

它是免费服务有如下限制

  • 1000个用户

  • 50MB的文件大小

除此之外AppHub的最大问题是对Swift和Android支持的情况并不好, 详见Will an Android Library be implemented soon?

Siphon

Siphon也是支持React Native应用的即时更新, BUT

Siphon is shutting down on 27th July 2016.
To our customers, users and supporters: unfortunately this is the end of the road for Siphon. Our long-term goal was to create the most developer friendly end-to-end publishing platform for mobile apps. 

Due to some inherent limitations in the early design decisions that we made (in particular the inability to compile your own native modules with Siphon) we have come to the regrettable conclusion that this vision is not possible at this time. We hoped that these native bridged modules would mature and become less important over time, but this has turned out to not be the case. 

All apps created using Siphon are fully compatible with the standard React Native framework and transferring your app should only take a few minutes. Please email us if you need any help migrating your app. 

Thanks to everyone who supported us over the past few months.

关于更多热补丁方案的比较, 可以参考CodePush vs. Siphon vs. AppHub

第三方库

Redux

Redux是什么?

Redux is a predictable state container for JavaScript apps

简单来说, Redux是

状态容器, 提供可预测化的状态管理. 可以跟大部分的View层框架配合使用不限于 React

那么React Native中的state又是什么呢?

在React中, 把所有的component看做有穷状态机, component由一个个的state来支撑, 有了不同的state, 即可重新渲染界面

Redux是Facebook官方针对React应用建议的架构, 想要了解Redux

Redux的三个要点

  • 应用中所有state以对象树形式存储在一个store中

  • 唯一改变state的方法是action

  • 通过action触发reducers来改变state树

Redux的三个原则

  • 单一数据源

  • state只读

  • 纯函数执行修改

Redux的三个组成

  • store - 即state的容器, 在Redux中, 只有一个store

  • action - 是一个对象, 并且约定好type字段为字符串, 用于表示action类型, 例如添加用户的action

{
  type: 'ADD_USER',
  data: {
    name: 'username',
    email: '[email protected]',
    psw: '123456'
  }
}
  • reducer - action通过reducer来完成state的改变, reducer在store中来分发处理action

react-native-material-kit

react-native-material-kit示例

移动开发中的React Native研究_第1张图片
react-native_03.gif

react-native-vector-icons

react-native-vector-icons的一句话介绍就是: 3000 Customizable Icons for React Native

react-native-app-intro

react-native-app-intro示例

react-native_04.gif

更多UI组件, 可以参考JS.COACH

开源应用

f8app

f8app是Facebook官方出品的

We've created a series of tutorials at makeitopen.com that explain how we built the app, and that dive into how we used React Native, Redux, Relay, GraphQL, and more.

react-native-nba-app

react-native-nba-app Info

  • Platform: iOS & Android

  • State Management: Redux

  • Code Style: Standard

  • Unit Test: None, take a look at snowflake for learning

  • Related Articles: Let’s drawing charts in React-Native without any library

react-weather

react-weather Development stack

  • Flow was enabled to catch typing errors in React Native JavaScript code

  • Realm for React Native is used to persist data

  • I used Nuclide and Visual Studio Code on OSX, both have great support for React Native app development

  • I used git for version control, and stored progress on GitHub.

  • Currently only tested on an iOS device

reading

reading Application Architecture

  • Microsoft Code Push for dynamic update

  • Redux is a predictable state container for reading application, together with React Native

  • Redux-Saga is a library that aims to make side effects in reading application easier and better

  • Mocha and Chai for UT

  • Enzyme for testing React Native UI components and mock

  • Eslint is a tool for identifying and reporting on patterns found in reading application code

更多应用可以参考学习React Native必看的几个开源项目(第一波)

总结

React Native的优势

  • Based on JavaScript and React

  • Learn Once, Write Anywhere

React Native的缺点

  • 版本仍在迭代中
react-native_01.png
  • Learn Once, Write many times
移动开发中的React Native研究_第2张图片
react-native_02.png
  • 对iOS的支持更早更好, 而android中的坑较多

React Native的比较

  • 大厂都是基于Hybrid: 钉钉, 微信, QQ音乐, 淘宝, 京东...

  • 使用React Native的大厂有携程...(其他暂时没找到了)

React Native与Hybrid开发都需要

  • 终端工程师需要有一定的web经验

React Native相比Hybrid的用户体验更好, 但是Hybrid在以下场景更有优势

  • 应用严重依赖网络并且对更新延时敏感

对于React Native的更多探讨, 可以参考Hybrid App 和 React Native 开发那点事, 我对 React Native 的理解和看法, 一个“三端”开发者眼中的React Native, React Native vs Ionic: A Side-by-Side Comparison

参考

  • awesome-react-native

  • react-native-guide

  • 写给iOS开发者的React Native学习路线

  • 江清清的技术专栏

  • 贾鹏辉的技术博客

更多文章, 请支持我的个人博客

你可能感兴趣的:(移动开发中的React Native研究)