React Native(RN)入门调研

背景

    公司要开发一款新的应用,一方面希望能像H5一样跨平台和动态更新,另一方面又不满原生嵌入H5这种性能瓶颈,于是我便开始进行一系列调研,包括RN、Flutter、Uni-app等,本篇文章主要给大家分享RN调研的一些结果。主要内容有:
     1、RN 是什么?
     2、RN 为什么出现,它带来了哪些好处?
     3、RN如何实现跨平台?
     4、RN热更新机制。
     5、RN是如何解决H5性能瓶颈的?
     6、RN快速上手步骤。
     7、RN有哪些缺点,未来发展方向。

RN是什么?

     RN是React Native的简称。其中React(有时叫React.js或ReactJS)是一套开源JavaScript 库(也可以称为前端 UI 框架),而React Native则是React向移动端的延伸。我们可以认为React Native分为两层,React 层是一套JavaScript 库;Native层则扮演桥梁的功能,根据平台不同映射为不同的原生控件;通过这种设计实现了—开发者构建的RN代码可以在不同的平台上(暂时支持Android和IOS)运行,也就是Learn once, write anywhere。
     问题A:为什么不是Write once, run anywhere呢?

RN 为什么出现,它带来了哪些好处?

     React 最初来自 Facebook 内部的广告系统项目,随着页面与逻辑越来越复杂项目的前端开发遇到了巨大的挑战:当更新一个页面元素,需要了解整个View DOM树和所有关联节点的业务等才能正确更新UI与业务逻辑,当页面复杂时候,这是一个很考验耐心的工作,很容易遗漏,所以他们有一种技巧,修改部分UI与逻辑,但是全部重新绘制渲染,这也是react的初步想法之一。
     简单、直观、可靠是软件攻城狮们孜孜不倦的追求!!
     为了达到上述目的,Facebook攻城狮对市场上所有 JavaScript MVC 框架进行审核,MVC需要通过C来绑定View监听数据变化,来实现级联(相关View的)更新。 但是在小框架上,V和 C往往很难分离,分离反而不利于阅读和理解代码。因此Facebook对主流的JS框架很不满,任性的他们就决定自己写一套,用来架设 Instagram的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了,这就是React。React设计目的就是解决目前JS框架不够直观和业务逻辑复杂的弊病,所以React 最有价值的是声明式的、直观的编程方式,这也是它这样命名的原因(React: 响应,一修改就可以很直观的看到效果)。

RN如何实现跨平台?

    在围绕原生与H5交互实践聊聊Android混合开发,我们有谈到H5能够实现跨平台的原因在于Android和IOS都实现了一个内置浏览器-WebView,分别通过Android和IOS上的这两个浏览器来解释运行H5。
    同理RN也是分别利用了Android和IOS的两个翻译器Jsc.so和JavaScriptCore,通过这两个翻译器RN代码就可以翻译成为Android或者IOS代码,从而在android或IOS系统上运行。具体可以参考文章:React Native运行原理解析
    总揽所有的跨平台技术,其实和指挥多国联合部队差不多,指挥官发出命令,每个国家的部队接收这个命令时,必须有对应的翻译系统将它翻译成本国语言,才能使之得到执行。所以每个翻译系统精准度、稳定度、效率都是衡量整个(多国作战系统)跨平台技术优异的指标。至于在每个国家如何构建精准、稳定、高效的解释翻译系统,则需要根据指挥官语言和这个国家语言进行针对性设计。我接下来会有文章对翻译解释系统进行讨论,欢迎大家在这里留言,提供想法。

RN热更新机制

     谈到RN不得不谈一谈它的热更新机制,在围绕原生与H5交互实践聊聊Android混合开发,有提到H5与生俱来的结构设计,是把数据和数据展示方式都当做数据从服务器下发,也就是说H5页面可以包含所有的业务逻辑和数据信息,它天生具有热更新机制。
     RN热更新的原理就是从服务器拉取新的JS bundle文件,并重新加载。具体可以看看通过对RN热更新的剖析来感受热更新思维一文。JS bundle,bundle: 捆,JS bundle一捆JS,可以认为是H5页面集合,对比H5一页页的拉取,RN是一次性拉取下来,并给这个集合一个版本号,如果版本更新再去拉取新的JS页面集合,一次性拉取下来之后,js就是本地文件,利用RN解释翻译器(JavaScriptCore)去解释执行RN代码(JS 集合中的JSX代码)。所以RN热更新的核心技术还是构建RN的解释器翻译器
    谈到这里,我有一个问题,问题B: 热更新思想的实质是什么?它的发展方向是什么?
    个人见解:
        热更新思想: 一切都是数据流( every thing is data flow)
        热更新核心技术: 构建跨平台解释(翻译)系统
大家有什么想法,请在下方评论。

RN是如何解决H5性能瓶颈的?

    首先我们需要了解H5性能瓶颈是怎么造成的?对比原生,H5包含信息更加自由丰富,这也导致:
    1、从服务器获取信息时候,H5页面需要更多的数据量和校验步骤,相应的需要消耗更多的时间;
    2、本地解析渲染(显示)时候,H5需要更复杂的解析渲染规则,相应的需要耗费更多的时间。
    RN可以认为是H5(JS)的特殊子集合。那么RN解决H5性能瓶颈,自然也是从这两点进行出发的。
    首先我们看问题1它关键在于正常使用时候减少网络请求的数据量。这一点我们其实已经从一个名词( JS bundle)中猜测到,RN相当于进入一个模块时候(可以自定义分包)把需要更新的的H5页面打包成一捆(js bundle,可能是一页,也可能是好几页)一次性更新,当再次加载该页面的时候,就直接从本地获取就行了。在这种方式下,当非首次加载JS bundles时候,从网络请求的数据跟原生基本差不多,甚至一些特定情况比原生还要少。所以问题1的答案就是是运用(批量)缓存的方式来减少平时使用过程中网络请求数据量。
    接下来我们再研究问题2,它关键在于缩短JS代码解析渲染的时间,为解决这个问题,Facebook采用了两个重要举措:
     1)引入虚拟DOM减少不必要的渲染;
     虚拟DOM、虚拟硬盘、虚拟机等计算机术语中提到的“虚拟”基本都是为了解决“真实”操作起来复杂、繁琐、代价高等问题而生,它们都能够将相对简单方便的虚拟操作映射成为真实的行动。虚拟DOM的出现之前,一次页面更新可能有十几个DOM更新操作,前前后后更新了十几次,大大浪费了渲染性能。出现虚拟DOM之后,一次更新操作中的10次更新DOM的动作,不会立即操作DOM,而是将这10次更新更新到虚拟DOM中,通过对比找出前后两次虚拟DOM的不同(diff算法),然后把不同一次性映射为真实DOM的更新。
     2)舍弃JS渲染,通过映射的方式把RN代码中的控件一个个映射为原生控件进行渲染。
    由于JS的灵活性与复杂性,虽然很多团队在研究它的渲染问题,但它的解析+渲染始终比原生慢上许多。于是facebook工程师另辟蹊径,它认为既然原生渲染快,那就用原生渲染代替JS渲染,RN做好桥接就好了。比如我们用RN代码写一个Button,那么实际在运行的时候RN会生成一个映射表,将这个Button分别映射为android和ios的button,相关设置的属性也进行了同步映射。
    从上面可以看到,正是出于对H5的性能优化和向移动端的延伸思维产生了RN,那我这里留下几个问题给读者:
    问题C:RN能否做到android端和IOS端统一,如果不能为什么,如果可以怎么做 ?
    问题D:RN代码在本地运行时是通过javaScriptCore边解释边运行,还是提前翻译成原生代码,甚至是机器码放在本地运行,facebook为什么这样设计?

RN快速上手步骤(已有实践的同学可略过)

一 、RN开发环境搭建

     请参考RN中文网-环境搭建

二、RN本地运行与调试

     1 、运行请参考RN中文网运行篇
     这里我仅仅解释下命令react-native run-android和(IOS 本地运行需要)npm start
     这两个命令都会在电脑上起一个服务进程Watchman,Watchman是由Facebook提供的监视文件系统变更的工具,这个服务进程起来后就会监听RN文件目录下文件是否变化,如果变化就把相关内容打包发送给手机,从而实现了本地热更新。(你的电脑相当于远程的服务器,手机从你电脑上获取新的JS bundle)。
     2、关于打开本地热更新,摇一摇手机打开本地热更新功能选择界面,或者在命令提示符窗口输入:adb shell input keyevent 82。
     3、 关于调试请参考RN中文网-调试

三、RN开发基本流程

     React 是一个全新思路的前端 UI 框架,它完全接管了 UI 开发中最为复杂的局部更新部分,擅长在在复杂场景下保证高性能;同时,它引入了基于组件的开发思想,从另一个角度来重新审视 UI 的构成。通过这种方法,不仅能够提高开发效率,而且可以让代码更容易理解,维护和测试,所以RN开发的一些流程和原则与原生有很大不同。
     1、绘制原型图,如果有直接用;
     2、列出所有需要使用的基础组,一个基础组件只负责一个功能;
     3、对基础组件进行分层;
     4、搭建静态页面;
     5、分析页面之间的关系;
     6、确定数据显示者和拥有者 ;
     7 、确定状态机变量最小集;
     8 、确定各个事件的接收者和处理者;
     9 、实现界面业务逻辑。

三、RN开发原则与规范

     1、不能用“this.state.某状态机变量名 = 值”来刷新页面。this.state.值是可以获取到具体state的值,但是它不会引发render,所以这样赋值是不会生效,牢牢记住state值是跟页面UI变化绑定的一起的。应该使用this.setState进行赋值, 因为setState异步的,而且会进行state状态合并,所以最好的是,时间顺序无关的state可以如下赋值:

this.setState({
                        bannerImageUrl:jsonContent.androidImgUrl,
                    }

如果一个state值连续改变,请传递一个方法到setState中确保setState能够正确执行,如下:

this.setState((state) => {
            return {
                number: number+1,
            }
        })
this.setState((state) => {
            return {
                number: number+2,

            }
        })

    2、如果跟ui无关的变量尽量不要定义在state中 ,会导致页面绘制。
    3、组件成员变量定义请用如下方式:this.myProperty='HaHa'
    4、尽量让自定义的组件成为无状态的React native 组件,无状态意思就是没有状态机 state。
    5、尽量创建多个无状态(只负责渲染数据)的React native 组件,将他们封装在 一个有状态的组件中,并把有状态值通过props 传给无状态的 react-native 组件。
    6、让UI中可变数据来源是状态机变量和属性。
    7、 遵循自底而上的设计开发原则。

RN有哪些缺点,未来发展方向

    从上面可以看出RN最大优势是开发者友好(声明式的,直观的编程方式),它基本原理在于提供一套从JS到原生的映射,从而实现JS代码拥有接近原生的运行效果。
    但是这种另辟蹊径的方式下的缺点也是有不少的,最明显的就是两端的不统一,JS在Android平台和IOS平台都映射为Android和IOS的原生View进行渲染,Android和IOS原生不一致的话,那么自然会出现双端不一致;其次这种多端桥接的方式,等于说RN兼容JS版本和原生版本,JS版本和原生版本不断进化千万万,做RN的同学很能体会到这种兼容性的坑;最后就是做RN需要会Android、IOS、JS这一整套全懂,学习成本高。
    随着5G的到来,端到端的传输速度大大增加加之新一代Web渲染引擎的研发,RN对WebView的性能优势逐渐失去;而RN多端不统一的问题越发尖锐,比如谷歌大佬推出的Flutter,用了一套全新的渲染机制,真正实现了一次书写,多端运行,但是由于多种原因比如dart语言的普及率、Flutter热更被禁止、Flutter社区不够成熟等,Flutter还未真正普及起来,但未来可期,强烈冲击着RN的地位。
    所以RN迫切需要变革,一方面强化自己的优势(入手快,直观、用户友好)保证React框架在前端的霸主地位,另一方面向Flutter学习做好多端统一。但不管RN的将来能重新繁荣昌盛还是成为历史云烟,RN值得每一个做技术的学习,它的简单、直观,它的桥接转换另辟蹊径。

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