React Native 项目总结

React Native这个框架出来,一直都受很多程序员的热捧。但是国内一直都是嘴上热捧,并没有那么多人几成到自己现有开发实际的项目,这段时间一直都在学习JS的内容,就试了试React Native,因为对android开发不熟悉,只能从一个iOS开发者来分析了。

优点

  • 无需编译,直接通过更新云端的js代码来实时更新应用app界面(这是最大的诱惑)
  • 降低了学习成本,所有native组件都是标签化的XML,对于一些前端程序员来说,降低了成本(但是,不懂Objective-C的话Brigde一些本地功能也是徒劳无功)
  • 有较强的扩展性,这是因为Native端提供的是基本控件,JS可以自由组合使用。

缺点

  • 没有Xcode那样一个可视化的IDE,不过看过一个 DECO 还没有可以下载,视频介绍显示的很牛的样子
  • 对app性能优化方便,还没有十足的把握,比如在遇到列表数据的时候,会出现抖动,因为只要state中属性变化就会刷新页面,虽然这个可以通过shouldUpdateComponent函数来过滤,但是依旧不是很理想。
  • 传大数据的时候性能也是问题
  • ios上面还一个大坑是三方app的js没法开启jit, 只有safari里面的js可以开启jit

从上面看来好像缺点还是真多,就不用了?当然也不是,当然有各种大牛如果很热衷于此,都会慢慢攻破技术难题, 这里推荐国内牛人的博客 江清情的技术专栏。那些对效果和性能不是要求很高的都可以用react native做, 那些与众不同的就不好用react native做了. react native相对h5而言有了很大的进步, 但react native和h5只能满足大家共用的需求, 比较特殊的需求的还得用原生做。

环境搭建

大家一个React Native(下面简称RN)应用跟着官网来就行了,基本思想官网也有解释

1
2
$ npm install -g react-native-cli
$ react-native init AwesomeProject

文件分析

在appdelegate中我们知道,应用启动第一个文件是指向index.ios.js这个文件就是我们需要管理的界面启动代码。分为三个部分(代码和原有生成的会不同)具体参考git开源的RN项目gitFeed

import组件
1
2
3
4
5
6
7
8
9
const React = require('react-native');
const RootTab = require('./AppComponents/RootTabComponent');
const GHService = require('./networkService/GithubServices');
const {
//要使用到的组件
AppRegistry,
StyleSheet,
ActivityIndicatorIOS,
} = React;

就相当于OC中引用了一个类,并同时创建一个实例。

JS代码bridge自定义OC组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#import <Foundation/Foundation.h>
#import "RCTBridgeModule.h"

@interface DXRNUtils : NSObject<RCTBridgeModule>

@end

#import "DXRNUtils.h"

static NSString * const kAppId = @"1079873993";

@implementation DXRNUtils

@synthesize bridge = _bridge;

RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(clearCookies:(RCTResponseSenderBlock)callback) {

}

RCT_EXPORT_METHOD(trackClick:(nonnull NSString *)eventName attributes:(NSDictionary *)atr) {
}

RCT_EXPORT_METHOD(appInfo:(RCTResponseSenderBlock)callback) {

}

@end

创建的类需要准从RCTBridgeModule协议,RN是通过Module切换到客户端源码,必须要在implementation中实现RCT_EXPORT_MODULE(),并在需要module的methond方法前添加RCT_EXPORT_METHOD来定义。云端JS代码必须要有一个相同的类与之对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
var React = require('react-native');
const Platform = require('Platform');

var {
NativeModules: {
DXRNUtils,
}
} = React;

var Uitls = {
clearCookie(cb) {
if (Platform.OS === 'android') {
// TODO:

} else if (Platform.OS === 'ios') {
console.log('clear cookies');
DXRNUtils.clearCookies((error, results) => {
if (error) {
console.log('clearCookie error occured' + error);
}
});
}
},

trackClick(name, atr) {
if (Platform.OS === 'android') {
// TODO:

} else if (Platform.OS === 'ios') {
DXRNUtils.trackClick(name, atr);
}
},

appInfo(cb) {
if (Platform.OS === 'android') {
// TODO:

} else if (Platform.OS === 'ios') {
DXRNUtils.appInfo((info) => {
cb && cb(info);
});
}
}
};

module.exports = Uitls;

在js中应用它是需要添加NativeModules关键字

1
2
3
4
5
var {
NativeModules: {
DXRNUtils,
}
} = React
;

创建组件
1
2
3
4
5
const AwesomeProject = React.createClass({
getInitialState() {},
getInitialState() {},
...
});

公开组件
1
module.exports = Uitls;

组件管理

一个简单的RN的项目就能成功的跑起来了,项目的文件基本分布是这样:

学过ReactJS就知道,React在H5方面是一个非常好用的框架,很多的git开源出来的组件都是通过React封装的给开发者提高了开发效率,比如wechat出的weui就是基于React写的一组控件,还有material-ui 等等。当然随着RN的盛行,很多的大牛也不断在完善我们可能需要使用到的各种组件。

在H5开发中,引用地方组件我们通过标签来管理,在iOS开发中我们使用pod工具类管理要引用的第三方开源库,那么在RN中使用npm(node package manager)来管理。pod添加开源库是通过Podfile文件来添加依赖项目地址,并进行安装,安装之后生成pod文件夹,被安装的工程都在pod文件夹中。npm则通过package.json来管理需要依赖的项目,并且会安装在项目的nodes_module文件夹中

网络请求

使用链式函数的fetch,它就是就是为了提供更加强大、高效的网络请求而生。使用 fetch 的构造函数请求数据后,返回一个 Promise 对象,处理即可。

fetch("http://blog.parryqiu.com")
.then((response) => {
   // do something...
})

GHService.login(state.username, state.password)
      .then(() => {
        this.props.navigator && this.props.navigator.pop();
        this.props.didLogin && this.props.didLogin();

        const nextPromise = this.props.nextPromise && this.props.nextPromise();
        return nextPromise;
      })
      .catch(err => {
        console.log('login error', err);
        this.setState({
          loginError: err,
        });
      })
      .done(() => {
        this.setState({
          logining: false,
        });
      })

EVENTS

使用框架 events,便于理解和兼容

1
2
3
4
5
6
7
8
9
10
发送事件
SingleGHService.emit('didLogout');

监听事件

SingleGHService.addListener('didLogout', () => {
this.setState({
userState: LoginState.unOnboard,
});
});

依赖管理

在实际开发过程中,经常需要同时运行和修改多个React Native工程,这样会带来了React Native自身的冗余,如果创建了十几个工程,那么多占用的空间轻松达到3GB以上,非常地不友好。我的解决思路是:用npm link替代npm install。可以参考下面文章 多React Native项目时依赖管理的最佳实践