【资料图】
原生侧createView方法的主要执行步骤为:
RCT_EXPORT_METHOD(createView: (nonnull NSNumber *)reactTag viewName: (NSString *)viewName rootTag: (nonnull NSNumber *)rootTag props: (NSDictionary *)props)1.根据模块名viewName从RCTBridge保存的全局变量中找到对应的模块信息2.根据模块信息创建shadowview虚拟dom,保存到shadowView全局容器中3.根据模块信息在主线程创建原生view,保存到view全局容器中然后,执行setChildren:设置子视图执行setChildren:设置子视图, 会将view添加到容器view的reactSubviews中(shadowView和UIView都是放到对应容器的reactSubviews属性中)[container insertReactSubview:view atIndex:index++];
原生侧setChildren方法的主要执行步骤为:
RCT_EXPORT_METHOD(setChildren : (nonnull NSNumber *)containerTag reactTags : (NSArray1.设置shadowView子视图,shadowView是设置到yoga树的叶子节点中:YGNodeInsertChild(_yogaNode, subview.yogaNode, (uint32_t)atIndex);2.把设置view子视图任务添加到任务队列,[_pendingUIBlocks addObject:block];队列中的任务并不会立刻执行,而是等到合适的时机再执行。而当这个任务执行后,子View也并没有到真实的subviews中,而是放置到了reactSubviews关联属性中 objc_setAssociatedObject(self, @selector(reactSubviews), subviews, OBJC_ASSOCIATION_RETAIN_NONATOMIC);_pendingUIBlocks队列执行时机在js执行期间,js引擎通过Bridge桥接,把涉及到UI操作的事件按顺序封装成UIBlock放到Native原生侧的_pendingUIBlocks中,在等js代码执行完成后,原生模块会触发一个UIManager.batchDidComplete事件,表示js批量任务执行完成,开始刷新uiPending队列中的UI任务了。因此,在 JavaScript 执行完成前,RN 页面的 UI 并不会立即刷新。方法调用顺序:batchDidComplete -> _layoutAndMount -> flushUIBlocksWithCompletion。_pendingUIBlocks中的UIBlock执行后,最终会生成真实的原生view*)reactTags)
- (void)didUpdateReactSubviews{ for (UIView *subview in self.reactSubviews) { [self addSubview:subview]; }}RN页面更新当组件调用了setState属性更新时,通过updateView:刷新视图。当出现插入、删除、排序组件时,通过manageChildren:更新视图。updateView:刷新视图当在RN中通过setState更改属性,js会对应生成一个新的虚拟DOM,通过diff算法,对应新旧DOM树生成修改点,然后通过updateView事件,将属性更新更新到原生侧的shadowView和View的_UIPendingQueue中。当出现插入、删除、排序组件时,通过manageChildren:更新视图containerTag:表示容器组件的标识符,即将在其中管理子组件。moveFromIndices和moveToIndices:表示要移动的子组件的原始位置和目标位置的索引。addChildReactTags和addAtIndices:表示要添加的子组件的标识符和它们在父容器中的位置索引。removeAtIndices:表示要从父容器中删除的子组件的位置索引。registry:表示React组件的注册表,其中包含所有已注册的组件及其实例。
Copyright 2015-2022 南极晨报网 版权所有 备案号:粤ICP备2022077823号-13 联系邮箱: 317 493 128@qq.com