众所周知,RN和H5的区别在于:RN是使用Native组件来渲染的,而H5是依赖WebView。那么RN是如何做到写js代码,渲染Native组件的呢,这篇文章我们深入源码,一探究竟。使用的RN版本是v0.62.0
JS侧的UI是使用React来实现的。熟悉React的同学,都知道React使用jsx来写布局,然后会转换成虚拟dom树,最后再渲染到浏览器的真实dom里,那React Native是怎么做的呢?
为了方便阅读,这里先把文中提到的一些函数列出来:
一、启动
以默认的demo为例,我们的代码入口在App.js
,并且导出了jsx渲染函数。
const App = () => {
return (
<View key={
'view-parent'} style={styles.parent}><Text key={
'text-1'} style={styles.text1}>
Hello World!Text><Text key={
'text-2'} style={styles.text2}>
zey RN TestText>View>
);
};
export default App;
在根目录的index.js里会把这个函数根据appName,注册进去。
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
看下注册函数:
registerComponent(
appKey: string,
componentProvider: ComponentProvider,
section?: boolean,
): string {
let scopedPerformanceLogger = createPerformanceLogger();
//存在runnales里
runnables[appKey] = {
componentProvider,
run: appParameters => {
//运行run的时候,开始执行渲染。
renderApplication(
componentProviderInstrumentationHook(
componentProvider,
scopedPerformanceLogger,
.....//省略
)
);
},
};
.....//省略
return appKey;
},
这里把渲染函数存在runnables
对象里。那么,是什么时候开始执行这里注册的runnables呢?这里就和客户端的调用有关了。
在启动RN页面时,客户端内部会调用下面这行代码,调用runApplication,传入对应的appName和一些参数。
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
然后在js里AppRegistry.js就会执行对应名称的注册函数:
runApplication(appKey: string, appParameters: any): void {
.....//省略
runnables[appKey].run(appParameters);
},
可以看到走到了renderApplication
里执行渲染逻辑。
再跟进去会发现有两个选择,ReactFabric和ReactNative,Fabric就是RN的新架构,现在最新的代码还是用的ReactNative:
GlobalPerformanceLogger.startTimespan('renderApplication_React_render');//渲染计时开始
if (fabric) {
require('../Renderer/shims/ReactFabric').render(renderable, rootTag);//令人期待的新框架Fabric
} else {
require('../Renderer/shims/ReactNative').render(renderable, rootTag);
}
GlobalPerforma