linux cpu占用率如何看
304
2022-09-27
你所不了解的React Native
1.1 React Native基本知识
React Native基于React框架而设计,因此,了解React有助于我们更好地理解React Native。
1.1.1 React简介
React是由Facebook推出的前端开发框架,其本身作为MVC模式中的View层来构建UI,也可以以插件的形式应用到Web应用程序的非UI部分构建中,轻松实现与其他JS框架的整合。同时,React通过对虚拟DOM的操作来控制真实的DOM,从而得到页面的局部更新,提高了GPU渲染的性能,而React提出的模块化开发思路也大大提高了代码的可维护性。
React的官方地址是DOM)
传统的Web应用开发,一般都是通过直接操作真实DOM来进行更新操作的,如图1-1所示,但对DOM进行操作通常是比较昂贵的。而React为了尽可能减少对真实DOM的操作,采用了一种强大的方式来更新DOM,代替直接的DOM操作,这就是Virtual DOM,一个轻量级的虚拟DOM。
图1-1 传统的Web应用结构图
虚拟DOM其实是React抽象出一个对象,通过这个Virtual DOM可以更新真实的DOM,由这个Virtual DOM管理真实DOM的更新,如图1-2所示。简单来说,React在每次需要渲染时,会先比较当前DOM内容和待渲染内容的差异,然后再决定如何最优地更新DOM,这个过程被称为reconciliation。
图1-2 React Web应用结构图
除了性能方面的考虑,React引入虚拟DOM更重要的意义在于提供了一种新的开发方式来开发服务端应用、Web应用和手机端应用,如图1-3所示。
图1-3 虚拟DOM结构图
Components组件
虚拟DOM(virtual-dom)不仅带来了简单的UI开发逻辑,同时也带来了组件化开发的思想。所谓组件,即自己封装的具有独立功能的UI部件。React推荐以组件的方式去构成视图,并建议将功能相对独立的模块抽象为组件。例如,Facebook的instagram.com网站都采用React来开发,整个页面就是一个大的组件。
对于React而言,界面被分成不同的组件,每个组件都相对独立。在React开发中,整个界面可以看成是由大小组件构成,每个组件实现自己的逻辑部分即可,彼此独立,如图1-4所示。
采用组件化开发,往往具有以下特点:
可组合(Composeable):一个组件易于和其他组件一起使用,或者嵌套在另一个组件内部。如果在一个组件内部创建了另一个组件,那么父组件拥有它创建的子组件,通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件。可重用(Reusable):每个组件都可以独立出来,被使用在其他相似的UI场景中。可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护。可测试(Testable):每个组件都是独立的,那么对于各个组件分开测试显然要比整个界面容易得多。
图1-4 Components组件示意图
数据流(Data Flow)
React采用单向的数据流,即从父节点到子节点的传递,因此更加灵活便捷,也提高了代码的可控性。React单向数据流可以总结为以下流程:Action→Dispatcher→Stroe→View,如图1-5所示。
图1-5 React单向数据流流程图
JSX语法
1.1.2 React Native简介
React Native(简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的UI框架React在原生移动应用平台的衍生产物,目前支持iOS和Android两大平台。
React Native可以基于目前大热的开源JavaScript库ReactJS来开发iOS和Android移动应用,因为往往只需要开发一套代码就可以满足iOS和Android,正如Facebook说的“Learn once, write anywhere”(仅需学习一次,编写任何平台),由于基于Web技术,React Natie开发起来可以像在浏览器那样随改即所见。
React Native的原理是在JavaScript中使用React抽象操作系统的原生UI组件,代替DOM元素来渲染界面,比如用 在UI方面,React Native提供跨平台的类似Flexbox的布局系统,还支持CSS子集。可以用JSX或者普通JavaScript语言,还有CoffeeScript和TypeScript来开发。运用React Native,我们可以使用同一份业务逻辑核心代码来创建原生应用运行在Web端、Android端和iOS端。 React Native相比Web开发或原生开发主要有以下特点: APP占用体积小 随着业务的迭代,原生APP的体积越来越大,特别是一些老的APP,动辄上百兆,而采用React Native之后,占用体积会大大缩小,而且引入React Native可以实现持续开发。 实现跨平台开发 基于Web技术(HTML5/JavaScript)构建的移动应用速度快,开发周期短,但是体验较差,响应不及时;而使用原生开发,周期长,项目风险不可控。如何提高开发效率,节约人力成本。成为各大公司考虑的问题,而React Native的出现解决了上面的问题,只需要开发一套代码,便可以同时部署到Android和iOS两个移动平台上。 相对成熟的技术 随着Android/iOS的React Native陆续开源,原生提供的组件和API相对丰富,且实现技术基本一致,对于熟悉前端和原生APP开发的人员来说很容易上手。而React Native通过JavaScriptCore将JS转换为原生APP组件进行渲染,其用户体验也可媲美原生APP。 支持动态更新 在原生APP开发中,Android平台可以通过插件化实现热更新。在iOS平台上,热更新策略是严令禁止的(如JSPatch/wax/rollout等技术),而采用React Native技术完全可以满足要求,而又不触碰苹果的底线。 1.1.3 React Native工作原理 使用JavaScript开发移动APP的想法来源于最近几年市场对于移动应用需求的增长,为了快速开发一款可以使用,而体验又不是那么糟糕的APP,很多公司投入大量人力开发跨平台应用。而在这些公司当中,Facebook无疑是做得最好、最成功的。 为了更好地理解React Native,我们需要对React Native的工作原理和整体架构有一个了解,如图1-6所示。 图1-6 React Native整体框架图 如图,React Naitve框架分为3层,分别为:JSX环境层、虚拟DOM层、具体的平台层。这里面最重要的就是虚拟DOM层。 在React中,Virtual DOM就像一个中间虚拟层,位于JavaScript和实际渲染页面之间。对于JS开发者来说,只需要专注于UI层的绘制即可,不需要特别关心具体平台的实现。 虚拟DOM是一个 JavaScript 的树形结构,主要包含React元素和模块。组件的DOM结构就是映射到对应的虚拟DOM上,React通过渲染虚拟DOM到浏览器,使得用户界面得以显示。React之所以更新界面高效,是因为React的虚拟DOM采用了batching(批处理)和高效的Diff算法,采用Diff算法,可以将时间复杂度从O(n^3)降到O(n),从而提高界面构建的性能。当需要更新组件的时候,会通过Diff算法寻找到要变更的DOM节点,然后通知浏览器更新变化的内容。 虚拟DOM更新视图的过程可以总结为:状态变化→计算差异(Diff算法)→界面渲染。其渲染的原理如图1-7所示。 图1-7 虚拟DOM更新原理图 在界面渲染过程中,React Native针对不同的平台调用原生API去渲染界面,例如iOS平台调用其原生的API去渲染iOS界面,Android平台调用其原生API去渲染Android界面,而不是直接渲染到浏览器的DOM上,这使得React Native不同于基于Web视图的跨平台应用开发方案,因而,采用React Native开发的APP,体验更加接近原生APP。 虚拟DOM和MVVM的对比 虚拟DOM只是MVVM框架的一种实现方案,二者没有好坏之分。在流行的前端框架中,除了React采用虚拟DOM之外,其他MVVM系框架,如Angular、Vue、Avalon,采用的都是数据绑定。 何为数据绑定?简单来说,就是通过观察Directive/Binding对象数据变化,并保留对实际DOM元素的引用,当有数据变化时进行对应的操作。React检查是DOM结构层面的,而MVVM的检查则是数据层面的。MVVM的性能检测也根据检测层面的不同而有所不同:Angular的脏检查使得任何变动都会产生固定的更新的代价;而Vue/Avalon采用的依赖收集,使得在JS和DOM层面都会产生更新。 上面提到两个概念—脏检查和依赖收集。 脏检查:scope digest +必要DOM更新依赖收集:重新收集依赖+必要DOM更新 可以看出,Angular效率低的地方在于任何小变动都会引起界面的重绘,但是,当所有数据都变化的时候,Angular并不吃亏。依赖收集在初始化和数据变化的时候都需要重新收集依赖,在数据流比较小的时候几乎可以忽略,但在数据量比较大的时候就会产生一定的消耗。相比之下,React的变动检查则是DOM结构层面的,即使是全新的数据,只要渲染结果没有变化,也不需要重新绘制。 Angular和Vue都提供了重绘的优化机制,即有效地复用实例和DOM元素。在优化的版本中,Angular和Vue采用了track by $index技术后比React的效率更高。 所以在框架选择和技术性能分析的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合,以及DOM、脏检查MVVM、数据收集MVVM在不同场合各自的表现和优缺点,具体表现和区别如下。 初始渲染阶段:Virtual DOM >脏检查≥依赖收集小量数据更新时:依赖收集>Virtual DOM +优化>脏检查(无法优化)> Virtual DOM无优化大量数据更新时:脏检查+优化≥依赖收集+优化>Virtual DOM(无优化)> MVVM无优化 1.2 React Native与其他跨平台技术的对比优势 曾经大部分开发者以为可以通过Web技术来实现跨平台移动开发,却因为性能限制或其他问题而放弃,最终,不得不针对多个平台开发多个版本,这违背了跨平台开发的初衷。而React Native的出现让跨平台移动端开发再次回到人们的视野中,而它提倡的“Learn once, write anywhere”也赢得了广大开发人员的青睐。相比传统的H5技术,React Native获得了更加接近原生应用的体验。 为了方便理解,笔者将跨平台技术分为四大流派。 Web流:也被称为Hybrid技术,它基于Web相关技术来实现界面及功能。代码转换流:将某个语言转成Objective-C、Java或C#,然后使用不同平台下的官方工具来开发。编译流:将某个语言编译为二进制文件,生成动态库或打包成apk/ipa/xap文件。虚拟机流:通过将某个语言的虚拟机移植到不同的平台上来运行。 1.2.1 Web流 Web流,如大家熟知的PhoneGap/Cordova等技术,它将原生的接口封装后暴露给JavaScript,然后通过系统自带的WebView运行,也可以使自己内嵌Chrome内核。 Web流缺点是性能差、渲染速度慢。说它Web性能差,主要说的是在Android下比较差,在iOS下已经很流畅了。 性能差的主要原因是,在Android和iOS的早期设备中,由于没有实现GPU加速,所以会造成每次重绘界面的卡顿。 而造成渲染慢的第二个原因是:CSS过于复杂。因为从实现原理上看,Chrome和Android View并没有本质上的差别,但过于复杂的CSS会加重GPU的负担。那是不是可以通过简化CSS来解决呢?实际上还真有人进行了这种尝试,比如著名的Famo.us,其最大的特色就是不使用CSS,只能使用固定的几种布局方法,完全依靠JavaScript来写界面,它能有效避免低效的CSS代码,从而提升机器性能。 造成绘制缓慢的第三个原因是,业务需求的复杂,比如超长的ListView商品展示。因为DOM是一个很上层的API,使得JavaScript无法做到像Native那样细粒度地控制内存及线程,所以难以进行优化,特别是在硬件较差的机器上。 上面三个问题现在都不好解决。其实除了性能之外,Web流更严重的问题是功能缺失。比如iOS 8就新增4000多个API,而Web标准需要漫长的编写和评审过程,而等到Web审核通过,即便是Cordova这样的优秀的框架,或者自己封装也是忙不过来的。所以为了更好地使用原生系统新功能,Native是最快的选择。 1.2.2 代码转换流 不同平台下的官方语言不一样,并且平台对官方语言的支持最好,这就导致对于同样的逻辑,我们需要写多套代码。比如Android平台用Java,iOS用Objective-C或者Swift。于是就有人想到了通过代码转换的方式来减少重复的工作量,这就是代码转换流。 这种方式虽然听起来不是很靠谱,但它的成本和风险都是最小的,因为代码转换后就可以用官方提供的各种工具了,和普通开发区别不大,而且转换后,利用原生的优势,可以减少兼容性问题。 目前存在以下几种代码转换方式。 将Java转成Objective-C 2objc是一款能将Java代码转成Objective-C的工具,据说Google内部就是使用它来降低跨平台开发成本的,比如Google Inbox项目就号称通过它共用了70%的代码,效果很显著。有了2objc,我们就可以先开发Android版本,然后再开发iOS版本。 将Objective-C转成Java MyAPPConverter是一款将Objective-C代码转换成Java代码的工具,比起前面的2objc,MyAPPConverter还打算将UI部分也包含进来,从它已转换的列表中可以看到还有UIKit、CoreGraphics等组件,使得有些应用可以不改代码就能转换成功。 XMLVM 除了上面提到的源码到源码的转换,在代码转换流中,还有XMLVM这种与众不同的转换方式,它首先将字节码转成一种基于XML的中间格式,然后再通过XSL来生成不同语言,目前支持生成C、Objective-C、JavaScript、C#、Python和Java。 虽然基于中间字节码可以支持多语言,但是这种方式也有一些问题,例如生成代码不可读,因为很多语言中的语法会在字节码中被抹掉,并且是不可逆的,所以不利于代码的调试和发现问题。 综上所述,虽然代码转换这种方式风险小,但对于很多小APP来说其实共享不了多少代码,因为这类应用大多数围绕业务来开发的,大部分代码都和业务逻辑耦合,所以公共部分不多,其意义不大。 1.2.3 编译流 编译流比代码转换流的代码转换更进一步,它直接将某个语言编译为普通平台下能够识别的二进制文件。采用这种方式主要有以下特点。 优点 可以重用一些实现很复杂的代码(比如之前用C++实现的游戏引擎,重写一遍的成本太高)。编译后的代码反编译困难,安全性更好。 缺点 转换过于复杂,并且后期定位和修改成本会很高。编译后体积太大,尤其是支持ARMv8和x86等CPU架构的时候。 常用的编译流方案如下所示。 C++方案 因为目前Android、iOS和Windows Phone都提供了对C++开发的支持。特别是C++在实现非界面部分,性能是非常高的。而如果使用C++实现非界面部分,还是比较有挑战的。这主要是因为Android程序的界面绝大部分是Java编写的,而在iOS和Windows Phone平台下可以分别使用C++的超集Objective-C和C++/C#来开发。要解决使用C++开发Android应用程序界面的问题,目前主要有两种方案。 通过JNI调用系统提供的Java方法。自己实现UI部分。 第一种方式虽然可行,但是代码冗余高,实现过于复杂。那第二种方式呢,比如JUCE和Qt就是用代码实现的。不过在Qt的方案中,Android 5版本或更高版本环境下,很多效果都没法实现,比如按钮没有涟漪效果。根本原因在于它是通过Qt QUIck Controls的自定义样式来模拟的,而不是使用系统UI组件,因此它享受不到系统升级自动带来的界面优化。 当然我们可以使用OpenGL来绘制界面,因为EGL+OpenGL本身就是跨平台的。并且目前大多数跨平台游戏底层都是这么做的。 既然可以基于OpenGL来开发跨平台游戏,那么,是否能用它来进行界面开发呢?当然是可行的,而且Android 4的界面就是基于OpenGL的,不过它并不是只用OpenGL的API,那样是不现实的,因为OpenGL API最初设计并不是为了实现2D界面,所以连画个圆形都没有直接的方法,因此Android 4中是通过Skia将路径转换为位置数组或纹理,然后再交给OpenGL从而完成界面渲染的。 然而直接使用OpenGL绘制界面,不仅实现的代价大,而且目前支持的平台少。因此对于大多数应用来说自己实现界面是很不划算的。 Xamarin Xamarin是从Mono发展而来,它用C#来开发Android及iOS应用,因为相关工具及文档都挺健全,因而发展得还不错。在UI界面方面,它可以通过调用系统API来使用系统内置的界面组件,或者基于Xamarin.Forms开发定制要求不高的跨平台UI。 从实现的方式来讲,iOS下是以AOT的方式编译为二进制文件的;而在Android平台上是通过内嵌的Mono虚拟机来实现,所以Xamarin是跨平台开发的不错选择。 对于熟悉C#的团队来说,Xamarin是一个很不错的方案,但这种方案最大的问题就是相关资料不足,遇到问题很可能搜不到解决方案,并且当前第三方库太少,加之Xamarin本身有些bug,所以让我们静待Xamarin做得更好吧。 Go Go做为后端服务开发语言,专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++程序的速度,而且更加安全、支持并行进程。Go从1.4版本开始支持开发Android应用(1.5版本支持iOS)。虽然能同时支持Android和iOS,但是目前可用的API很少,Go语言仍然专注于后端开发。 目前,Android的View层完全是基于Java写的,要想用Go来完成界面的开发不可避免要调用Java代码,而在这方面Go还没有简便的实现方式,目前Go调用外部代码只能使用Cgo,通过Cgo再调用jni,这就不可避免地需要写很多的中间件。而且Cgo的实现本身就对性能有损失,除了各种无关函数的调用,它还会锁定一个Go的系统线程,这会影响其他gorountine的运行,如果同时运行太多外部调用,甚至会导致所有go线程处于等待状态。 所以,目前使用Go开发跨平台移动端应用并不靠谱。 1.2.4 虚拟机流 编译流是将代码编译为不同平台下的二进制文件,而另一种更彻底的做法是:通过虚拟机来支持跨平台运行,比如JavaScript和Lua都是天生的内嵌语言。不过使用虚拟机进行跨平台开发最普遍的两个问题是:性能损耗;虚拟机本身也会占据不小的空间。 Java虚拟机 说到虚拟机,大家肯定首先想到的是Java,因为Java一开始就是为跨平台而设计的,Sun的J2ME早在1998年就有了,在iPhone手机出来之前,很多小游戏都是基于J2ME开发的。前几年,微软为了支持移动端项目的发展,提供了一套将Android和iOS代码快速转移到Windows Phone的工具,不过后来不了了之。 前面提到C#和Java在iOS端的方案都是通过AOT的方式实现的,目前还没见到有Java虚拟机相应的方案,主要原因是iOS方面的限制。 Titanium/Hyperloop Titanium和PhoneGap几乎是同时期的著名跨平台方案,和PhoneGap最大的区别是:它的界面没有使用HTML/CSS,而是自己设计了一套基于XML的界面框架Alloy。Titanium的代码风格如下: APP/styles/index.tss".container": {backgroundColor:"white"},// This is APPlied to all Labels in the view"Label": {width: Ti.UI.SIZE,height: Ti.UI.SIZE,color: "#000", // blacktransform: Alloy.Globals.rotateLeft // value is defined in the alloy.JS file},// This is only APPlied to an element with the id attribute assigned to "label""#label": {color: "#999" /* gray */} 虽然学习成本低,但Titanium同样面临着其他跨平台框架都存在的挑战:缺乏第三方库支持、对外的API较少。Titanium也意识到了这个问题,所以目前在开发下一代的解决方案Hyperloop,它可以将JavaScript编译为原生代码,这样开发者可以方便地调用原生API。比如调用iOS的写法如下: @import("UIKit");@import("CoreGraphics");var view = new UIView();view.frame = CGRectMake(0, 0, 100, 100); 这个方案和之前讲到的Xamarin如出一辙,也是将JavaScript翻译为Objective-C,然后交由官方系统运行。不过这个项目已经开发了快三年了,但至今仍然是试验阶段,笔者不建议尝试。 React Native React Native是由Facebook开源的基于JavaScript和React搭建的一套跨平台开发框架。在设计之初,React Native采用的方案就是在不同平台下使用平台自带的UI组件来完成界面的绘制,再加上它采用JavaScript和React等前端语言来开发,所以获得了不少前端程序员的青睐。 有人说,React Native采用JS等前端技术来开发移动APP是回归H5,但其实React Native和Web扯不上太多关系,React Native虽然借鉴CSS中的Flexbox、navigator、XMLHttpRequest等API的写法,但是大部分还是通过原生的组件或者自己封装的组件来开发的。就像Facebook的内部软件Facebook Groups,iOS版本很大一部分基于React Native开发,其中用到了不少内部通用组件。 React Native相比传统原生开发,学习成本还是比较低的,熟悉JavaScript的开发者可以迅速实现界面,而使用标签加CSS样式表方式绘制的界面,远比原生使用代码绘制的界面更加易读,并且一套界面同时满足Android和iOS平台,这对于讨厌绘制界面的开发者来说是多么的诱惑。再加上React Native师出名门,截至目前,React Native已更新到0.4.4版本,并且趋于稳定。由于其更加接近原生的体验,国内一些大厂纷纷加入,诸如阿里、腾讯、美团等纷纷开始使用React Native改造一些应用型APP。 所以,不管是对于个人还是团队,现在跨平台开发做得最好的就是React Native,并且随着开源力量的加入,React Native会发展得越来越好。 1.3 小结 使用React Native开发跨平台移动APP是一个令人振奋的事情,相比其他跨平台方案,React Native在不牺牲用户体验和应用质量的前提下,提高了开发效率,使用一套代码即可实现在Android、iOS和Web平台上运行,节约了成本得到了广大移动开发者的追捧。 本章主要从React Native的发展历程和工作原理等方面对React Native做了一个简单的介绍,并横向比较了当前主流的跨平台方案。纵观目前的跨平台方案,你会发现React Native是目前最好的跨平台技术,如果你的团队正在进行跨平台开发或者考虑跨平台开发,不妨试试React Native。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
,用
发表评论
暂时没有评论,来抢沙发吧~