码迷,mamicode.com
首页 > 其他好文 > 详细

初探React Native

时间:2016-07-14 15:45:45      阅读:350      评论:0      收藏:0      [点我收藏+]

标签:

PS该报告偏向理论层面,技术层面由于本人才疏学浅属于前端小白因此暂时未作过多研究。

技术分享

一、React Native相关介绍

简介

React Native是Facebook开发的一套框架,其目的在于使用JavaScript语言开发原生APP,目前iOS版本和Android版本均已开源。

框架定位

下图摘自React Native官网首页:

技术分享

翻译:

React Native使你能够基于javaScript和React开发世界级的原生APP,其焦点在于开发效率,因为你能够用它来开发多个平台的应用(包括iOS和Android)。换句话说:learn once, write anywhere. Facebook目前已经使用React Native开发了多个原生应用,并将持续完善这套框架。

可以看到,React Native框架本身的定位在于提升移动端应用开发效率。再看看一个“webView”打天下的Hybrid应用,React Native是否也能够一套代码实现两个平台的“一劳永逸”呢?虽然我觉得不能说完全否定,但是基本是不可行的。

官方对于React Native的描述是 learn once, write anywhere ,而并非是 write once,run anywhere. 也就是说,React Native的跨平台,指的是可以用React Native编写两个平台的应用,而不是一套React Native代码可以同时在两个平台上跑。原因在于React Native开发的是原生应用,iOS端和Android端的大部分控件是无法整合到同一个JS端组件或API上的。事实上,只有少数的组件及API能够垮平台使用。因此,简单地说,一个应用,依旧两套代码,只不过可以由一套框架(并不绝对)、一个RN团队来完成。

技术分享

(以下对“React Native”或以“RN”简称)

涉及技术栈

JSX语法

说到RN的语法,不得不提到React(即React.js)。React同样是脸书开源的一套前端框架,核心语言javaScript毋庸置疑,另外其采用组件化的方式构建界面,这在语法上则需要HTML的支持;对于界面布局,采用的则是一贯的CSS方案。可能你要一脸懵逼了,心想这不就是大名鼎鼎的前端三剑客吗?是的!然而React将HTML、CSS、javaScript黑魔法般地整合到一起,自成规则,成就了一种全新的语法:JSX。而React Native采用的,正是React的这套语法。说白了,React+RN,JS一统三端了!另外,RN已经支持了ES6语法。

服务器端

使用Node.js作为javaScript的运行环境,其内置了V8引擎。就作为一名RN开发者而言,对于Node的认识即便一片空白实际上也无伤大雅。

二、React Native运行(基于iOS)

环境搭建(MAC OS)

  1. 安装软件包管理工具 homebrew
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

  2. 安装node.js(或者从官方下载 node.js
    brew install node

  3. 安装watchman,watchman用来监视文件并且记录文件的改动情况
    brew install watchman

  4. 安装flow(flow来为js代码加上类型检查,根据需要是否安装)
    brew install flow

  5. 更新上述程序,保持最新版本(本人配置好环境后未执行该命令更新上述程序版本,工程运行报错,更新后运行正常)
    brew update && brew upgrade

  6. 安装RN的命令行工具,通过npm安装
    npm install -g react-native-cli

  7. Ok,万事俱备!

创建工程

通过命令行创建第一个RN工程learn_rn: react-native init learn_rn 运行完毕后会在当前目录创建一个 learn_rn 文件夹,这个就是RN工程所在的文件夹。

open learn_rn 工程目录如下:

技术分享

  • iOS与android文件夹 :默认创建的iOS工程和android工程文件夹
  • index.ios 与 ndex.android :分别为iOS和Android工程对应的JS入口文件
  • package.json :配置文件
  • node_modules :react native依赖库

回忆刚刚执行 react-native init learn_rn 是不是install了很长时间。原因有二。

  1. react native依赖库体积庞大,查看 node_modules 文件夹大小,足足90多兆;
  2. react native依赖库是从npm服务器拉取的,而npm服务器并不在国内,可以通过翻墙来解决此问题,也可以通过修改npm镜像源。目前npm最常用的是淘宝的镜像源。

运行工程

现在,打开iOS文件夹,运行.xcodeproj工程文件,再熟悉不过的XCode界面。直接Run,最终模拟器会显示一个默认的界面。

技术分享

分析一下从Run到界面加载的过程发生了什么,首先是JS端的启动工作:

  1. 编译原生工程代码
  2. 编译完毕之后,自动启动(在XCode做了配置)Node.js服务器
  3. 从JS入口文件开始,分析模块之间的依赖关系,转换JSX语法,把转换后的模块打包成一个bundle.js文件并部署到Node服务器。至此,JS端初始化完毕。

接着是原生端的启动工作:

  1. 如同正常的iOS工程一样,调用main函数,创建UIApplication实例,创建AppDelegate实例,启动消息循环,开始监听app的运行。
  2. app启动后,方法didFinishLaunchingWithOptions被调用,这个方法中根据jsCodeLocation创建了一个RCTRootView对象,这个jsCodeLocation就是之前打包好的bandle.js地址,是从server上访问的。
  3. 原生与JS开始通信,最终在原生端创建好相应的控件显示在界面上。

热加载

来对项目作一点小小的修改。打开index.ios.js文件,暂且不对源码作介绍。将源码中 “Welcome to React Native!” 修改成 “Hi!I’m Lotheve”保存。 这个时候,打开模拟器,然后 Command+R ,神奇的事情发生了,界面瞬间刷新成修改后的效果。

前端程序猿估计要直呼大惊小怪了,然而对于一个没见过什么世面的原生程序猿,习惯了对任何源码的修改都要重新Run一次工程以适应修改,这样的体验简直要飞!揪其原因,很简单,js代码是跑在服务器上的,每次reload,服务器重新加载代码,实时刷新原生界面(事实上,并不是刷新整个UI,而是只刷新diff部分,这在下面将会介绍)

原生嵌入React Native

在刚才的介绍中有提到,RN的界面是通过一个RCTRootView对象显示的,这个RCTRootView是UIView的子类,因此很容易地可以在原生中嵌入React Native。具体步骤如下:

  1. 安装React Native依赖库
  2. 通过cocoaPods安装需要的React Native依赖工程
  3. 创建index.ios.js入口文件并编写相应的代码
  4. 原生引入头文件#import

三、React Native特性

UI更新逻辑

原生中,界面的更新往往由控制器来控制,RN则是通过“状态机”的机制来驱动UI更新的。RN中,整个UI是一个Component树,由一个个Component构成,最终被编译成一个虚拟DOM,加载到内存中。另外,每一个Component可以定义一种叫“state类型”的属性,当这种类型的属性值发生变化时,系统会定位到响应的DOM组件,并计算出DOM的diff信息,根据这个“diff”来驱动UI的更新。

RN的这种UI更新机制,保证了每次只刷新需要目标UI,避免的整个UI的刷新,从而保证了UI渲染的效率。React Native UI更新机制如下图:

技术分享

React Native通信机制

对于一个RN应用程序,编码工作主要在RN端,因此RN与原生的通信主要探讨RN端如何实现JS调原生。

就iOS而言,React Native与原生之间的通信并不是采用JavaScriptCore提供的可以让两者互调的一些方法(例如webView的stringByEvaluatingJavaScriptFromString、通过获取JSContext交互、以及拦截协议等 PS本人已知的就这么多),而是在此基础上自己实现了一种机制,这套机制能够通用于所有JS引擎上,从而与安卓的V8引擎形成了一种通用的机制。

关于React Native通信机制,bang的这篇博客个人觉得已经分析得非常到位,我就说一下我对React Native通信机制的简单理解。

RN中JS调原生主要是采用了一种叫“模块配置表”的东西,它本质是一个json文件。原生暴露给JS的类及方法,称之为模块类和模块方法。在模块配置表中,保存了这些模块类的集合以及类中模块方法对应的的集合。这个模块配置表会分别保存一份在iOS端和JS端,当JS调用原生的某个方法时,从JS端的模块配置表中找到对应的模块类id和模块方法id,然后传递给iOS端,从iOS端的模块配置表中还原出对应的原生方法调用之。

简单的流程如上所述,如果要回调,只不过是JS端多传了一个回调id给iOS,iOS执行完毕相应的方法之后会回传回调id给JS端,由JS端执行实现保存的JS回调代码。另外关于JS端是如何将id传递给iOS的,这个问题在bang的博客里有说明,说是采用事件响应的机制,个人不是很理解,猜测是原生在JS线程中通过NSTimer事件不断调用JS,通过将id以返回值的形式传给JS。

下面附上大神博客中给出的调用流程图:

技术分享

四、React Native性价比分析

优缺点分析

优点:

  1. 复用了React的思想,有利于前端开发者涉足移动端。
  2. 原生级别的交互体验
  3. 相对于原生平台,开发速度更快;相对于Hybrid平台,性能更好。

缺点:

  1. 做不到 Write once, Run everywhere,也就是说开发者依然需要为 iOS 和 Android 平台提供两套不同的代码,比如参考官方文档可以发现不少组件和API都区分了Android和iOS版本。即使是共用组件,也会有平台独享的函数。

  2. 由于 Objective-C 与 JavaScript 之间切换存在固定的时间开销,所以性能必定 不及原生。比如目前的官方版本无法做到 UItableview(ListView) 的视图重用,因为滑动过程中,视图重用需要在异步线程中执行,速度太慢。这也就导致随着 Cell 数量的增加,占用的内存也线性增加。

  3. 由于RN版本目前还处于萌芽期,版本更新那叫一个快。然而有的迭代更新,会将部分支持老版本的代码在新版本中废除,使得原先开发的APP在版本迭代之后运行直接崩溃。这个问题目前无解,你根本就无法预测下一版本会做什么修改,而只能去适应修改!除非你永远不需要更新你的应用!

    官方对版本迭代的说明是每两个星期更新一次,目前官方official版本为0.29(当前时间2016.7.13)

技术分享

  1. 由于安卓版本刚开源没多久,资料匮乏。

学习成本

  1. RN是面向前端开发人员提供的移动端开发框架,个人认为其,对于不懂前端技术的移动开发者来说,学习RN还是有很大学习成本的。

  2. 尽管npm提供了大量的RN组件或者API,但是万一现有代码包无法满足实际需求,就要自己定制原生模块,通过桥接的方式在RN中使用。因此RN开发不能做到完全屏蔽iOS端或Android的技能,开发者必须对原生平台有所了解。这样看来,要想吃透RN,几乎是通吃3个端了,学习成本是非常高的。

五、总结

RN的诞生,不过是给web开发者向移动进军提供了桥梁,对于移动开发者,我认为并未有太大吸引力,至少对于我而言如此。

初探React Native

标签:

原文地址:http://blog.csdn.net/lotheve/article/details/51900867

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!