ReactNative 开发实践

序言

这是一个在StuQ做分享时的讲稿。当然还有很大的改进空间,但我这会却没有什么劲头继续改进,既然这样就不如索性先发出来,先把它从脑袋清出来,把其它我更想做的事情做了,回头再看哪天想改了再回来改。

当然,大家有觉得不对的地方,随便批,我会当做问题之一,以后努力改进:)

分享环节:

00.jpg

大家好,我是深圳平安科技的利炳根。网名:清醒疯子。主要研究iOS和ReactNative。
今天和大家分享的是我在ReactNative上的一些开发实践经验。请大家多多指教。

在ReactNative上的研究,我还是做得比较粗浅,有不对的地方,大家随便批,我多向大家学习。

01.jpg

今天的内容分为四个部分。分别的ReactNative的开发环境搭建、JS/Bundle的管理、混编以及数据流的处理。

3.pic.jpg

ReactNative的开发环境搭建比较简单。只需要把node、watchman、flow通过brew安装完,通过npm把ReactNative命令行安装到全局,就可以用init命令创建ReactNative项目。

其中,node是node.js。它有非常好用的包管理工具npm。也可以拿来写后台。我自己经常拿来在本地快速写一些简单的后台辅助调试代码。

watchman是Facebook的开源项目,主要用来监视文件,记录文件的改动。React通过watchman来实现代码发生变化时完成相关的重建功能。

flow也是Facebook的开源项目,用来做JavaScript的静态类型检查。用来发现JS程序里的类型错误,提高编码效率和代码质量。包括前期错误检测、代码智能提示等。

安装ReactNative命令行的时候要注意加上-g这个参数,把RN命令行安装到全局,才方便我们在任何目录通过命令行创建ReactNative项目。

ReactNative项目创建的时候,会自动把一些需要用的库加到项目工程里,自动做好基本的依赖管理,并且自动生成最简Demo代码。创建完之后就可以运行一个最简单的Demo,方便大家体验ReactNative的编程。

4.pic.jpg

目前,ReactNative还没有特别好用的开发工具。开发效率会稍微打点折扣。但利用现有的开发工具还是足够完成基本的开发任务的。

Nuclide是Facebook的开源项目,是与Ract配套的IDE。目前还在不断地完善当中。已经能实现基本的代码提示和静态类型检查。Nuclide目前还不是独立的IDE,需要作为Atom的包进行安装。

Atom和WebStorm都可以做到React的部分代码提示。对ReactNative的支持就相对差一些。主要还是针对JavaScript的支持而已。

ReactNative的JSX只是JavaScript的封装。一些在JavaScript上的打包工具,ReactNative也能用。比如Browserify和Webpack。

Browserify使用比较简单。指明入口点和出口点就可以打包。而Webpack则一般要写一个配置文件webpack.config.js指明打包细节。当然,Webpack的功能相对就更强大一些。

Nuclide的开源项目代码提交还是比较活跃的,对这方面有兴趣的朋友不妨关注一下,参与其中和大神一起做一个IDE也不失为一种相当不错的娱乐项目。

5.pic.jpg

虽然ReactNative最终会渲染成Native的View,但它只能通过浏览器调试。基本上就是用Chrome来做。

Chrome上有一个插件React Developer Tools,不过要翻墙才能装。

通过Chrome的consle可以打印变量。如果对这块不熟悉的话,可以先通过调用一个网络请求,打印返回的数据,并根据数据调整显示,来熟悉一下Chrome的调试过程。

在JavaScript代码中插入debugger;就可以作为调试过程中的断点。

6.pic.jpg

在iOS平台上,ReactNative组件通过RCTRootView这个类接入到Native的视图层次里头。

RCTRootView初始化只需要提供两个参数,一个是JS包的路径,一个是模块的名称。

ReactNative的应用组件,最后渲染出来都是一个View的子类,都可以通过addSubView加到Native的视图层次上面。

7.pic.jpg

ReactNative可以实现动态编码。只需要在远端修改JS文件并保存,Native端无需重新编译,只需要Reload刷新一下,就可以更新APP视图和功能。

在设置RCTRootView的JS包地址时,设置为远端的JS文件资源网址,在引用时把文件后缀改为.bundle,即可以调用远端的ReactNative bundle命令,把对应的JS文件打包为可用的JS包文件,在Native端实现视图的渲染。

bundle命令有两个常用的参数。platform参数指定打包到iOS平台还是Android平台。dev参数指定是否开启开发选项以提供更多的调试信息。

8.pic.jpg

调用远端JS文件打包的方式有一个缺点,打包过程导致视图初次加载比较慢,影响用户体验。可以过加载离线包的方式解决这个问题。

在设置RCTRootView的JS包地址时,设置为Native端沙盒内的jsbundle文件地址,ReactNative就可以从Native端加载渲染视图,速度有明显提升。

通过bundle命令,可以把JS文件打包成jsbundle包。bundle命令有三个常用参数。platform参数指定平台,entry-file参数指定入口文件,bundle-output参数指定出口文件。

9.pic.jpg

通过加载Native端离线包jsbundle文件,在提升加载速度的同时也让ReactNative失去了远端更新的能力。这样得不偿失。我们可以通过静默下载jsbundle文件替换Native端jsbundle文件的方式解决这个问题。

通过远端jsbundle文件资源网址,启动一个下载文件请求。在收到请求返回的时候设定文件路径。在收到返回数据时写文件。

写文件时,要注意先让写入点移动到文件末尾,再进行文件写入,避免覆盖之前接收到的数据。

10.pic.jpg

ReactNative因为技术发展不久,还有部分Native端的功能并没有完全实现。在项目开发过程中有可能需要在ReactNative项目里加入Native端的功能代码辅助。

ReactNative有一套机制实现。在Native端的类里引用RCTBridgeModule,并遵循RCTBridgeModule协议。通过宏RCT_EXPORT_MODULE向JS暴露Native端的类,通过宏RCT_EXPORT_METHOD暴露Native端的方法,通过RCTResponseSenderBlock实现JS端的回调。

11.pic.jpg

JS端的处理和Native端同样简单。在JS文件的开始引用NativeModules组件。通过NativeModules引用Native端指定类。由Native端指定的类就可以直接调用指定的方法并指定回调的实现。

12.pic.jpg

Native项目添加ReactNative模块稍微复杂一点。首先需要进行一些工程配置。把ReactNative需要的静态库加到工程里。在Build Settings里设置Other Linker Flags 和Header Search Paths。最后还要在Info.plist里设置App Transport Security Settings -> Allow Arbitrary Loads。

13.pic.jpg

在Native的类中引用RCTBridge和RCTEventDispatcher。通过bridge的eventDispatcher向JS端派发事件。派发事件的接口有5个,分别对应5个不同的事件类型。

这里要注意,不要在Native端的viewDidLoad方法里向JS发送事件消息,因为这个时候ReactNative组件还没有挂载出来,接收不到消息。

14.pic.jpg

JS端在文件一开始引用NativeAppEventEmitter组件。通过NativeAppEventEmitter组件的addListener方法监听Native端派发的事件消息。组件卸载时,通过NativeAppEventEmitter组件的removeAllListeners方法移除监听。

15.pic.jpg

ReactNative的数据流处理,目前业内有4种方案。原生的ReactJS通过Props - States - Components的机制处理数据流。

缺点很多。扩展性差,增加新功能时,需要在每一个用到的组件里复制一遍代码。

可读性、可维护性差,代码量大,难以调试、测试。

可移值性差,代码耦合度高,视图、数据不分层。

违背单一数据层原则,在视图层直接进行数据操作。

16.pic.jpg

Facebook官方推荐的Flux,通过Actions - Dispatcher-Stores - Component的机制处理数据流。

代码冗长,Dispatcher和Store有很多重复烦琐的人工检查、定义。

多个Store中处理同一个Action,将产生大量的waitFor方法处理Store的先后逻辑。

多个Store间共享一个State,State有可能被分散到多个Store中,State的变化将变得不可控。

多个Store互相依赖,还有可能产生依赖循环。

17.pic.jpg

Redux通过Actions -Store - Components的机制处理数据流。

Redux针对Flux做了不少优化。通过内部拓展actions的行为,移除了单例的dispatcher。stores可以监听actions的行为,无需进行冗杂的switch判断。

stores可以相互监听,可以进行进一步的数据聚合操作。waitFor方法被连续和平行的数据流所替代。

Redux也有自身的一些弊端。由于整个应用的数据都集中在1个Store里,数据和处理逻辑的复杂度将不可避免地变高。

因为语法相似,从ReactJS、Flux迁移到Redux成本较低,建议旧项目迁移采用Redux。

18.pic.jpg

Baobab通过Actions -Baobab Tree - Components的机制处理数据流。

Baobab的优点十分明显。应用所有状态都存在一棵数据树里。可以非常简单地实现数据域的切换。应用状态树的存在使得数据流管理变得非常简单,代码量少。

通过Baobab库创建状态树,数据以键值对的方式存储。

Baobab通过select方法直接切换数据节点,还可以通过cursors创建数据游标组,访问数据。

Baobab通过set方法修改数据。

如果项目新建,没有旧代码维护的包袱,个人建议采用Baobab来处理数据流,一定会更省事省力。

结束语:

我的分享到此结束,非常感谢大家今天来参加,希望上面分享的内容能对大家有所帮助。如果大家对ReactNative或者其它问题想跟我交流,欢迎到我的支付宝经费群来。

19.pic.jpg

问答环节:

1.能说说选择相较PhoneGap,ionic等些其他平台,为什么选择React么?
PhoneGap是比较早期的技术,一直以来,在性能上或者功能的覆盖上,大家都不够满意。尤其是性能。RN因为最终是渲染成Native的View ,体验上就好很多。同时呢,因为RN是Facebook在推,从Github上的Star,大家也可以看出业界还是对Facebook有很大的期待和信心的。

2.请问rn中的组件出现相互嵌套的问题可以怎么解决?即 a require b, b 也require a。当调用a时,就会b=null了。可以用es6的模块解决吗?
这就是涉及到数据流的处理。如果用原生的ReactJS去处理,是会非常麻烦的。Facebook希望Flux能解决这个问题,但实际下来,大家觉得满足不了需求。然后业界就有了Redux和Baobab两种方案。Baobab是最新的方案,解决方式也最优雅,大家有兴趣可以重点研究一下。

3.既然是在Mac下,为什么不用safari调试,当前safari调试窗口也是很棒的
在我自己这边主要是习惯问题。一直以来用的都是Chrome。因为很早之前调试API啊各种东西都是用Chrome搞。既然Chrome能搞定就懒得换了。

4.Native与js调用时,与hybrid方式的app有什么不同。
RN的双向通信还是做得比较好的,上面的分享也有讲到,实现起来非常简单。我在这上面多花了一点时间,也只是因为把发消息的代码放到了AppDelegate上,结果死活收不到。Hybrid,常见也是用Bridge。这块的麻烦是,需要HTML5的同事配合。

5.再请教一个问题。组建多层嵌套时,组建间该如何通信?特别是最底层跟顶层的通信,除了props之外,还有啥好办法吗
这个其实就是第四部分数据流的处理问题。Baobab可以把数据统一到一个地方,而且数据域切换非常方便,可以看看。

6.提问:React Native对安卓的支持情况,是否能兼容如此碎片化的安卓
目前,我们还没有去处理具体的适配。这块因为主要是Android的同事在研究,我也不大清楚。不过,既然很多大厂都有用RN,应该不会有太大问题。

8.没有ios经验,只有reactjs经验的,怎么上手xcode下react native开发配置呢,或者android下的
Native下的工作量是非常少的。基本上只要随便找几篇入门的文章看看,问题就不大了。遇到搞不定的问题多上stackoverflow搜搜。或者找我交流也可以:)

9.rn在开发团队中的分工如何,如界面,js,ios程序员如何合作
目前我们是1个iOS和1个Android,然后就是后端了。其实重点的开发量反而是JS上的。一旦把平台需要配合的东西摸清,剩下的主要工作量就是写JS了。两个平台的多数组件都是可以共用的,也就是很多代码只要写一份就可以了。

11.rn适合渲染view还是处理各种逻辑呢,有不如原生的地方吗
目前为止,我还是学习RN就算是View上也做得没有Native漂亮。如果逻辑比较复杂,是不是适合全部用RN来做,还有待考察。RN目前主要的针对点还是迭代比较快的相对轻一点的业务。反正熟悉之后,混编是非常简单的事情,大不了拿Native做一个复杂业务的API:)

问题回答完毕:)

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

推荐阅读更多精彩内容