转载自:http://www.jianshu.com/p/b88944250b25javascript
React Native 诞生于 2015 年,名副其实的富二代,主要使命是为父出征,与 Apple 和 Google 抗衡,为开发者带去一套跨平台、动态更新的 Javascript 框架,口号是:Learn once, write anywhere:Build mobile apps with React。在试图推翻 Android 和 iOS 压制的同时,还提携了一把自家兄弟:React。html
从诞生之日 React Native 就充满了期待和争议。期待是无数开发者但愿不用忍受频繁发版的噩梦,也不用同时为两个平台开发业务逻辑几无差异的两个 App;争议是 React Native 真的能以一己之力救大众于水火吗?React Native 在跨平台时还能保持良好的用户体验吗?前端
固然咱们知道,这种问题向来都是仁者见仁,智者见智。比起一味的疑惑、争论,还不如来好好看看这货到底是个啥?甚至本身动手来玩一把。java
本文主要针对两类读者:node
下面咱们来看下 Hybrid 及 React Native 等开发模式包含了哪些常规移动开发所不具有的优点。react
传统的客户端开发模式是怎样的呢?android
Android 与 iOS Team 分别编写客户端代码,打包,分发到 Play Store 和 Apple Store,经过更新 JSON 数据来更新页面。ios
不过,当客户端发生严重问题而服务器上没法 quick fix 时,就不得不从新发版。git
对国外 Android 市场而言还好,由于能经过 Play Store 快速更新;国内 Android 市场则因为分发渠道太杂,很难及时把新版本当即推送给全部用户,固然这也是为什么热修复技术在国内盛行而国外冷清的缘由;而 Apple Store 则须要必定的审核时间,并且最近又在抓 iOS 热修复框架如 JsPatch、Rollout 等。程序员
相比而言,Hybrid 和 RN/Weex 模式除了能下发 Json 数据来刷新界面内容,更能直接下发业务逻辑代码,直接实现总体 App 的更新。并且,它们不用在意 Android 和 iOS 两个平台,由于一份 JS 代码写好后,把 JS Bundle 放在服务器上,全部的客户端当即更新。
通常而言,同一款产品的 Android 和 iOS 两端除 UI 有些许不一样外,多数业务逻辑几乎彻底一致,这便形成了人力的浪费。
而最近 Instagram 的官博 React Native at Instagram 一文中已经提到,利用 RN (React Native 缩写,下同) 开发的 feature 能够实现 85% - 99%
的代码复用率。这意味着咱们能够用更少的人力成原本达到相同的效果。
实现上面的效果有两种开发框架:混合开发框架 Cordova 和基于 Javascript 的 React-Native、Weex 框架。
下面我从本身的实践经验出发作些比较,也欢迎读者提出本身见解。
最开始以为 RN 的学习成本比较大,因此首先考虑了 Weex 框架,听说是阿里巴巴良心出品。不过在尝试后不得不选择了放弃,缘由有这几点:
最基本
的 ListView,在 iOS 运行良好,而一样的 Demo 代码到了 Android 这边的下拉刷新
就出现了问题,这使得咱们开始警戒;固然,我是很但愿国内也能推出优质的开源项目来和国外大厂抗衡的,不过真正优质的大型开源项目每每除了开发者的我的能力,和公司的战略和制度关系也很大。
这里的 Hybrid 开发主要针对 Cordova 框架,其实在放弃 Weex 以后咱们仍是没考虑 RN,而是转过去了解 Cordova,不过作了大体了解后也放弃了。主要硬伤有两点:
性能和用户体验是移动 App 的命根子。
所以,综合考虑下来,咱们仍是决定相信 Facebook 并采用 RN。
上面我提到了 RN 的一些优点,不过做为开发者更加须要明确其劣势,我总结了下大概有如下几点劣势:
split apk
的技术就能缩小到到 1MB 左右的增幅。对于一个用 RN 搭建的移动 App,在启动后会从服务器下载最新的 JS Bundle 文件,而后由本地 JavascriptCore 引擎对 JS 文件进行解析,并利用 Bridge 映射到对应的 Native 方法和 UI 控件。获得的效果是:
首先 IDE 方面,RN 推荐了一些工具:
本人的话目前采用的是 Sublime
,由于我的经常使用 Sublime,并且第三方插件很丰富,轻量方便。下面简单说下配置,感兴趣的小伙伴能够看下。
固然,用 Atom 的小伙伴天然要首先考虑 Nuclide。
引入 RN 有两种方法:从零构建;集成到已有项目。
先说第一种,从零开始构建,比较简单,遵循官方文档 Getting Started 基于你本身的操做系统和平台一步步安装相关的依赖,而后利用以下命令:
react-native init AwesomeProject
你就建立好一个 RN 工程项目了,结构以下:
里面有四个文件夹:
android
/ ios
:各自存放了一个相关平台的工程 project,能够直接下拉 JS Bundle 并运行,对于移动端小白而言能够不用管里面的具体实现;node_modules
:里面是自动生成的 node
依赖之类的文件,经过读取 package.json
里的配置来生成;js
:这个文件夹最为重要,咱们的开发都在这个文件夹里,把写好的 js
文件打包下发给 client 就会自动生效。有不少公司是但愿在现有 App 的基础上集成 RN
来开发一些特定的 Feature,这种状况就不能参考上面的方法了。在 RN 的官方文档里有一节 Integration with Existing Apps , 只须要按照一步步作便可。
以 Android 为例,大概要作如下几步:
gradle
依赖:compile "com.facebook.react:react-native:+" // From node_modules.
;Activity
,指定 JS bundle
和入口 Component
名字即会自动在这个 Activity
里去加载 JS bundle
文件;总之须要说明的是,即便是移动端小白,也能够遵循文档里的指示完成这一步。接下来的大部分时间只要关心 JS 端开发就好了。
咱们知道 RN 采用了 React 和 ES6 的语法,因此咱们必须先对这些语法有必定了解才能去读 RN 的代码。
关于 Javascript
,我推荐 W3School 里的 JS语法 和 MDN 里的 JS手册,你们只要对一些基础语法作些了解就能够。
关于 React
,我推荐 阮一峰 写的 React 入门实例教程,基本上把文章读一遍,再本身动手写一遍,就能理会到 React 的大体用法了。
关于 ES6
、ES7
、JSX
等,感兴趣的能够看一下 RN 文档中 Javascript Environment 里提到的支持的方法,须要时再来查询也能够。也能够看 Babel
出的 Learn ES2015 手册。
这里有一个很不错的 GitHub 项目,帮助你经过交互性的例子来快速上手语法知识:React Native Express。
简单熟悉了 React
语法后,基本能正常阅读 RN 的示例代码了。
正式开发 App 的第一步固然就是写 UI 界面了,因为 RN 已经封装好了一套 JS 的 UI 组件,这些组件会自动在 Android/iOS 端调用对应的原生 UI 组件,所以咱们只须要熟悉这些 UI 组件的用法及属性、回调方法便可。
咱们能够在文档的 Components 看到很多组件,好比View, Text, Button, Image, Switch
, 还有咱们用的最多的 ScrollView
和 ListView
。
在读文档时,咱们能够先经过一边写代码一边读文档的方式进行,RN 很是贴心,直接在 Web 里嵌入了模拟器,咱们只要修改编辑框里的代码,当即就能在右边的模拟器看到效果。这极大的下降了咱们的学习成本。
另外,在学习一个组件时,咱们要区分哪一个属性是某个平台特有的。好比下面两个 Text 的属性:textBreakStrategy
只会在 Android 上生效,而 adjustsFontSizeToFit
只能够用在 iOS 上。
而后,若是你但愿在 Android 和 iOS 里显示不一样的内容怎么办呢?RN 里有一节是Platform Specific Code,能够有以下几种形式来进行区分:
if (Platform.OS === 'ios') { // stuff for ios } else { // stuff for android }
除此以外,UI 组件的用法学习就很相似常规的 Html 标签了,只要知道其使用方式便可,甚至须要用的时候再来查文档也行。
学完上面的咱们已经可以写出 UI 界面了,并且这套界面已经可以在不一样平台上转化成各自平台的 Native UI 了。而后,咱们就须要去网络层请求真实数据了。
RN 里提供了 Fetch API 来进行实现。举个例子,你想要经过 GET 方法去请求数据并转化成 JSON,能够经过以下代码实现:
fetch('https://facebook.github.io/react-native/movies.json') .then((response) => response.json()) .then((responseJson) => { return responseJson.movies; }) .catch((error) => { console.error(error); });
熟悉 Reactive 编程的伙伴应该对这样的语法不陌生,好比 Android 上的 RxJava; iOS 上的 RxSwift;Web 上的 RxJS。上面 function 的功能就是:请求网址 https://facebook.github.io/react-native/movies.json
,把返回的 Response 转化成 JSON object,取出 JSON object 里的 movies
字段。同时,若是发生 error 会被 catch 住。
固然,上面是最基本的 GET 请求,Fetch API 还支持自定义 Headers,更换 Method,添加 Body 等。
fetch('https://mywebsite.com/endpoint/', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ firstParam: 'yourValue', secondParam: 'yourOtherValue', }) })
上面构建了一个基本的 POST 请求,添加了本身的 Headers:Accept
和Content-Type
,添加了 Body。
所以看下来,RN 里的网络请求不只具有了 Reactive 编程的简洁,也能自定义常规的 Http 请求,写法简单。
除了 Fetch API 以外,RN 还内置了 XMLHttpRequest API(俗称 AJAX),并且支持TCP 全双工通讯方式 WebSocket。
调试是不少程序员很是关注的一个环节,由于 RN 是用 JS 写完后到 Native 解释成 Native 方法来执行的,所以若是能快速调试 JS 代码是很是重要的一环。
最开始 RN 的调试功能比较弱,不过如今的 Debugging 功能在我看来仍是很不错的。通常来说能够有如下几个调试方式:
RN 里默认集成了 In-App 的错误提示方式,即在 App 运行过程当中会弹出全屏的报错信息呈现给你,而你也能够经过阅读具体的错误信息快速找到错误缘由。经过点击这个错误信息里的某一行,会当即自动打开对应的代码。
在开发 Client 时,咱们通常都会用 Log.log()
来打印一些运行时变量的值,而后实时查看打印出来的 log 来调试,在 RN 也同样,你只要在 JS 里写一句 console.log('this is log data')
,就会自动在 Client 的常规 log 里能看到,好比 Android 的 adb logcat
里就会自动打印出'this is log data'
一行。
这个杀器的最牛逼之处就是能够像 Client 同样,逐行调试代码!
咱们来看下面一张图。从左往右。先是文件目录,咱们选中了 index.js
文件夹,而后第二个 Tab,是 index.js
的内容。这里关键的是我能够直接选中某一行代码设断点。当 Client 运行到这一行时,就会在第三个 Tab 里打印出运行时环境及变量。咱们能够看到 props
里就有咱们传进去的变量值。
有了以上几种调试方式,咱们几乎能够和常规的 Native 开发同样来调试 RN 代码了,不得不说 RN Team 确实牛 x 啊!
这又是另外一个牛 x 之处啊。
不少人以为 RN 限制太多,只能支持有限的 View 组件和有限的方法,难以发挥 Client 的最大性能。简单点说,在 Client 能够绘制复杂的 View,能够调用高性能 C++ 等底层代码,但 RN 却作不到。
因而,RN 里提出了 Native Modules
和 Native UI Component
两种技术。
所谓 Native Modules,就是本身在 Client 写好了某些方法,因为某些缘由这些方法不太方便或者没法搬到 RN 里面,那么,咱们能够在 Client 把这些方法暴露出来给 RN,而后在 JS 里能够像 import 普通的 module 同样把这些 Native Modules 引入进去,直接调用。
具体的实现方法能够参考文档 iOS Native Modules 和 Android Native Modules。
不少时候咱们在写 Client 时,为了实现 Designer 天马行空的设计,经常须要自定义 View,即本身绘制某些系统并不提供的特定 UI。可想而知,这些 View 确定不会出如今 RN 的 UI Component 里。
那么,咱们就须要首先在 Native 层本身写好一个自定义 View,而后利用Native UI Component
技术把这个 View 及其中某些 public 方法暴露给 RN,那么 RN 就能直接 import 进来并显示了。
具体的实现方法能够参考文档 iOS Native UI Component 和 Android Native UI Component。
若是读过文档不是很理解的小伙伴能够留言,我再 post 一些 demo 代码上来
这里借鉴下前段时间旧金山的 React Native 会议上的一些优劣总结给读者以参考。固然不必定对,仅供参考。
RN 的优势:
RN 的缺点:
适合下面这些人/公司:
下面这些人要稍微考虑下:
几个月前我对 React Native 也很是不看好,固然如今也没有说很是看好。或者说,写这篇文章毫无为 React Native 布道之意。
接触 React Native 主要是由于业务须要,PM 但愿可以随时改动某块变化较大的模块,常规的开发提交流程每每须要较长的时间,而热修复技术自己并未获得 Google 和 Apple 的官方承认,也就是随时可能因破坏生态安全之名被取缔。
所以才考虑去了解 Hybrid 开发和 JS Native 开发模式,在了解过程当中,又因为性能差、用户体验很差而放弃 Hybrid,因为社区不完善、Bug 较多等缘由放弃 Weex,最终才选择了 React Native,开始学习 React、JSX等语法。
目前使用下来对 React Native 的一些我的感觉:
6MB
左右的 size 增幅,不过在采用了 split apk
后就只有 1MB
左右增幅。关于React Native一直以来都有不少争议。
不过我想说的是,React Native 所表明的跨平台、动态更新技术已经引发了全世界开发者关注,并且这种技术势必会是将来的需求和潮流。React Native 不必定会成功,但至少目前 React Native 已是这一领域的领跑者。
而写这篇文章的目的,就是但愿告诉更多开发者,React Native 并不完美,但值得一试。
谢谢。