React Native 原理解析

1、Virtual DOM

状态改变了要操作相应的 DOM 元素,为什么不做一个东西可以让视图和状态进行

绑定?让状态变更视图自动跟着变更,就不用手动更新页面了。这就是后来的 MVVM

式,只要在模版中声明视图组件是和什么状态进行绑定的,双向绑定引擎就会在状态

更新的时候自动更新视图,MVVM 可以能很好的降低维护状态以及减少视图的复杂程度。

一旦

态发生了变化,就用模版引擎重新渲染整个视图,然后用新的视图更换掉旧的视图。

当用户点击的时,还是在 JS 里面更新状态,但是页面更新就不用手

作 DOM 了,直接把整个表格用模版引擎重新渲染一遍,然后设置一下 innerHTML 。

么这个方法会有个很大的问题,会导致 DOM 操作变慢,因为任何的状态变更都要

新构造整个 DOM,性价比很低。对于局部的小视图的更新,这样没有问题(backbone

就是这么干的)。但对于大型视图,需要更新页面较多局部视图时,这样的做法就非常

可取。

DOM 很慢一旦浏览器接收到一个 HTML 文件,渲染引擎 Render Engine

就开始解它,根据 HTML 元素 Elements 对应地生成 DOM 节点 Nodes,最终组成一

棵 DOM 树。

 

构造了渲染树以后,浏览器引擎开始着手布局 Layout。布局时,渲染树上的每个节点根

其在屏幕上应该出现的精确位置,分配一组屏幕坐标值。接着,浏览器将会通过遍历渲染树,

调用每个节点的 Paint 方法来绘制这些 Render 对象。Paint 方法根据浏览器平台,使用不

同的 UI后端 API(Agnostic UI Backend API)通过绘制,最终将在屏幕上展示内容。只要

在这过程中进行一次 DOM 更新,整个渲染流程都会重做一遍。


DOM 我们都可以用 JavaScript 对象来表示。那反过来,就可以用 JavaScript 对象表示的树结

构来构建一个真正的 DOM 。当状态变更时,重新渲染这个 JavaScript 的对象结构,实现视图

的变更,结构根据变更的地方重新渲染。

 

这就是所谓的 Virtual DOM 算法:

用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文

档当中当状态变更时,重新构造一棵新的对象树。然后用新的树和旧的树进行比较两个数的差异。

然后把差异更新到久的树上,整个视图就更新了Virtual DOM 本质就是在 JS 和 DOM 之间做

了一个缓存。既然已经知道 DOM 慢,就在 JS 和 DOM 之间加个缓存。JS 先操作 Virtual DOM

对比排序/变更,最后再把整个变更写入真实 DOM。

https://www.cnblogs.com/wubaiqing/p/6726429.html


React

  • React 是由Facebook推出的一个JavaScript框架,主要用于前段开发。
  • React 采用组件化方式简化Web开发
    • DOM:每个HTML界面可以看做一个DOM
    • 原生的web开发方式,HTML一个文件,javaScript一个文件,文件分开,就会导致修改起来比较麻烦。
    • 可以把一组相关的HTML标签和JavaScript单独封装到一个组件类中,便于复用,方便开发。
  • React 可以高效的绘制界面
    • 原生的Web,刷新界面(DOM),需要把整个界面刷新.
    • React只会刷新部分界面,不会整个界面刷新。
    • 因为React独创了Virtual DOM机制。Virtual DOM是一个存在于内存中的JavaScript对象,它与DOM是一一对应的关系,当界面发送变化时,React会利用DOM Diff算法,把有变化的DOM进行刷新.
  • React是采用JSX语法,一种JS语法糖,方便快速开发。


作者:袁峥
链接:https://www.jianshu.com/p/5cc61ec04b39
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

对于 Android 开发者来说, RN是一个普通的安卓程序加上一堆事件响应, 事件来源主要是JS的命令。主要有二个线程,UI main thread, JS thread。 UI thread创建一个APP的事件循环后,就挂在looper等待事件 , 事件驱动各自的对象执行命令。 JS thread 运行的脚本相当于底层数据采集器, 不断上传数据,转化成UI 事件, 通过bridge转发到UI thread, 从而改变真实的View。 后面再深一层发现, UI main thread 跟 JS thread更像是CS 模型,JS thread更像服务端, UI main thread是客户端, UI main thread 不断询问JS thread并且请求数据,如果数据有变,则更新UI界面。


JS 也是单线程事件循环

JAVA层会把JS 关心的事件通过bridge直接使用javascriptCore的接口执行固定的脚本, 比如"requrire (test_module).test_methode(test_args)"。此时,UI main thread相当于work thread, 把系统事件或者用户事件往JS层抛,同时,JS 层也不断调用模块API或者UI组件 , 驱动JAVA层完成实际的View渲染。JS开发者只需要监听JS层framework定义的事件即可。

https://blog.csdn.net/xiangzhihong8/article/details/52623852

四、React Native如何把React转化为原生API

  • React Native会在一开始生成OC模块表,然后把这个模块表传入JS中,JS参照模块表,就能间接调用OC的代码。
    • 相当于买了一个机器人(OC),对应一份说明书(模块表),用户(JS)参照说明书去执行机器人的操作。

五、React Native是如何做到JS和OC交互

  • iOS原生API有个JavaScriptCore框架,通过它就能实现JS和OC交互,想了解JavaScriptCore,请点击JavaScriptCore
    • 1.首先写好JSX代码(React框架就是使用JSX语法)
    • 2.把JSX代码解析成javaScript代码
    • 3.OC读取JS文件
    • 4.把javaScript代码读取出来,利用JavaScriptCore执行
    • 5.javaScript代码返回一个数组,数组中会描述OC对象,OC对象的属性,OC对象所需要执行的方法,这样就能让这个对象设置属性,并且调用方法。

六、React Native启动流程(iOS)

  • 1.创建RCTRootView -> 设置窗口根控制器的View,把RN的View添加到窗口上显示。
  • 2.创建RCTBridge -> 桥接对象,管理JS和OC交互,做中转左右。
  • 3.创建RCTBatchedBridge -> 批量桥架对象,JS和OC交互具体实现都在这个类中。
  • 4.执行[RCTBatchedBridge loadSource] -> 加载JS源码
  • 5.执行[RCTBatchedBridge initModulesWithDispatchGroup] -> 创建OC模块表
  • 6.执行[RCTJSCExecutor injectJSONText] -> 往JS中插入OC模块表
  • 7.执行完JS代码,回调OC,调用OC中的组件
  • 8.完成UI渲染

七、React Native加载JS源码流程(iOS)

  • 1.[RCTJavaScriptLoader loadBundleAtURL] -> 加载远程服务器中JS代码
  • 2.attemptAsynchronousLoadOfBundleAtURL(C函数) -> 开启异步加载JS代码
  • 3.[RCTBatchedBridge executeSourceCode:sourceCode] -> 让批量交接对象执行源代码
    1. [RCTJSCExecutor executeApplicationScript] -> 交给JS执行者(RCTJSCExecutor)执行源码)
    • 真正执行JS代码的是RCTJSCExecutor对象
  • 5.[postNotificationName:RCTJavaScriptDidLoadNotification] -> 发送JS代码执行完成通知
  • 6.RCTRootView监听到RCTJavaScriptDidLoadNotification通知
  • 7.创建RCTRootContentView
  • 8.获取RCTBridge中的RCTUIManager注册RCTRootView,并且记录RCTRootView,_viewRegistry
    • RCTUIManager:管理UI组件
    • _viewRegistry:保存所有注册的View
  • 9.[RCTRootView runApplication:bridge] -> 通知JS运行App
  • 10.[RCTBridge enqueueJSCall:@"AppRegistry"
    method:@"runApplication"
    args:@[moduleName, appParameters]
    completion:NULL] -> 通过桥接对象让JS调用AppRegistry
  • 11.[RCTBatchedBridge _actuallyInvokeAndProcessModule:module method:method arguments:args queue:RCTJSThread] -> 通过批量桥架让JS执行AppRegistry方法
  • 12.[RCTJSCExecutor _executeJSCall:bridgeMethod arguments:@[module, method, args] unwrapResult:unwrapResult callback:onComplete] -> 让JS执行者调用JS代码
  • 13.执行完JS代码,就能获取执行JS结果,是一个数组,OC需要做的事情都会保存到这个数组中
  • 14.[RCTBatchedBridge _processResponse:json error:error] -> 处理执行完JS代码返回的结果对象
  • 15.[RCTBatchedBridge handleBuffer] -> 处理JS返回的数据,JS会返回的方法调用数组:按顺序描述需要调用哪个对象的方法,一组调用包含(module,method,arguments)
  • 16.[self callNativeModule:[moduleIDs[index] integerValue]
    method:[methodIDs[index] integerValue]
    params:paramsArrays[index]] -> 遍历数组,依次执行原生方法
    • 注意:当前方法,在遍历数组中的代码块中执行,不只是执行一次.

八、React NativeUI控件渲染流程(iOS)

  • 1.[RCTRootView runApplication:bridge] -> 通知JS运行App

  • 2.[RCTBatchedBridge _processResponse:json error:error] -> 处理执行完JS代码(runApplication)返回的相应,包含需要添加多少子控件的信息。

  • 3.[RCTBatchedBridge batchDidComplete] -> 批量桥架对象调用批量处理完成方法

  • 4.[RCTUIManager batchDidComplete] -> RCTUIManager调用批量处理完成的方法,就会开始去加载rootView的子控件。

  • 5.[RCTUIManager createView:viewName:rootTag:props] -> 通过JS执行OC代码,让UI管理者创建子控件View

    • 通过RCT_EXPORT_METHOD宏定义createView这个方法
    RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTag
                  viewName:(NSString *)viewName
                  rootTag:(__unused NSNumber *)rootTag
                  props:(NSDictionary *)props)
    
    • RCT_EXPORT_METHOD宏:会在JS中生成对应的OC方法,这样JS就能直接调用
    • 注意每创建一个UIView,就会创建一个RCTShadowView,与UIView一一对应
    • RCTShadowView:保存对应UIView的布局和子控件,管理UIView的加载
  • 6.[RCTUIManager _layoutAndMount] -> 布局RCTRootView和增加子控件

  • 7.[RCTUIManager setChildren:reactTags:] -> 给RCTRootView对应的RCTRootShadowView设置子控件

    • 注意:此方法也是JS调用OC方法
  • 8.[RCTRootShadowView insertReactSubview:view atIndex:index++] -> 遍历子控件数组,给RCTRootShadowView插入所有子控件

  • 9.[RCTShadowView processUpdatedProperties:parentProperties:] -> 处理保存在RCTShadowView中属性,就会去布局RCTShadowView对应UIView的所有子控件

  • 10.[RCTView didUpdateReactSubviews] -> 给原生View添加子控件

  • 11.完成UI渲染

九、React Native事件处理流程(iOS)

  • 1.在创建RCTRootContentView的时候,内部会创建RCTTouchHandler
    • RCTTouchHandler:继承UIGestureRecognizer,也就是它就是一个手势
      • 并且它会作为RCTRootContentView的手势,这样点击RCTRootContentView,就会触发RCTTouchHandler
    • RCTTouchHandler:内部实现了touchBegin等触摸方法,用来处理触摸事件
  • 2.在创建RCTTouchHandler的时候,内部会创建RCTEventDispatcher
    • RCTEventDispatcher:用来把事件处理传递给JS的方法处理,也就是当UI界面产生事件,就会执行JS的代码处理。
  • 3.通过RCTRootContentView截获点击事件
    • 产生事件就会去触犯RCTRootContentView中的RCTTouchHandler对象。
  • 4.当产生事件的时候,会执行[RCTTouchHandler touchBegin]
  • 5.RCTTouchHandler的touch方法,会执行[RCTTouchHandler _updateAndDispatchTouches:eventName:]
    • 内部会创建RCTTouchEvent事件对象
  • 6.[RCTEventDispatcher sendEvent:event] -> 让事件分发对象调用发送事件对象
    • 内部会把事件保存到_eventQueue(事件队列中)
  • 7.[RCTEventDispatcher flushEventsQueue] -> 让事件分发对象冲刷事件队列,就是获取事件队列中所有事件执行
  • 8.[RCTEventDispatcher dispatchEvent:event] -> 遍历事件队列,一个一个分发事件
    • 分发事件的本质:就是去执行JS的代码,相应事件。
  • 9.[RCTBatchedBridge enqueueJSCall:[[event class] moduleDotMethod] args:[event arguments]]; -> 让桥架对象调用JS处理事件
    • 本质:就是产生事件调用JS代码
  • 10.这样就能完成把UI事件交给JS代码相应





作者:袁峥
链接:https://www.jianshu.com/p/5cc61ec04b39
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

React Native Android 源码框架浅析(主流程及 Java 与 JS 双边通信)

https://blog.csdn.net/yanbober/article/details/53157456



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值