React Native 是一个由 Facebook 于 2015 年 9 月发布的一款开源的 JavaScript 框架,它可以让开发者使用 JavaScript 和 React 来开发跨平台的移动应用。
跨端技术
- 一次编写,多端运行
- 节省人力,加快迭代速度,支撑业务高速发展
WEB开发是最常见的跨端技术
-
优点
- 无需发版(开发完上线就可以看到效果)
- 节省人力(不需要为多个端投入不同的人力)
- 迭代速度快(前端写html和css开发比客户端开发快很多)
-
缺点
- 体验及性能比原生应用差
- 优化难度大(通常涉及到浏览器内核的修改,并且能得到的提升非常有限)
web开发与原生开发对比
- web: 采用动态语言开发,生成网页视图
- 原生:采用静态语言开发,生成原生视图
能不能结合WEB开发和原生开发的优点,用动态语言,生成原生视图?🧐
核心原理
🤩 如何通过JS生成原生视图?
Virtual DOM
- 描述用户界面的js对象
- 具备平台无关性
基于Virtual DOM和渲染器的分离,React在Render层将具体平台对应的渲染逻辑封装起来,来处理和平台相关的视图渲染。
将不同的基础库放在Render里面!!我们只需要关心怎么写virtual dom就可以了~
浏览器端如何创建视图
-
如何表示一个React元素
两种方法将react 元素传递给React DOM的render方法, 渲染到浏览器指定的html元素里面
//case 1
class App extends React.Component {
}
ReactDOM.render(<App />, document.getElementById("container"))
//case 2
ReactDOM.render(<h1>Hello world</h1>, document.getElementById("container"))
react中用一个对象表示元素
var element = {
//This tag allow us to uniquely identify this as a React Element
$typeof: REACT_ELEMENT_TYPE,
//built-in properties that belong on the element
type: type, //这个元素的类型
key: key, //这个元素的标识
ref: ref, //这个元素的引用
props: props, //元素的一些属性 (里面children表示这个元素的子元素)
//Record the component responsible for creating this element
_owner: owner
}
转化后的样子如下
//Case 1
<h1><p>Hello world</p></h1>
{
type: 'h1',
props:{
children: {
type: 'p',
props: ['Hello world']
}
}
}
//Case 2
<App/>
{
type: App,//Component
}
-
React Element 归类
-
原子类型(对应case1)
- type为字符串
- 粒度最小,结构上不可再分解
- 渲染:由平台底层提供支持
- 浏览器中为基础的html标签,Native端为基础UI组件
-
组合类型(对应case2)
- type为函数构造器(Virtual DOM生成器),提供自定义元素UI和行为的能力
- 渲染:
先使用类型构造器创建一个实例并运行render方法得到一个新的元素,再进行渲染
-
渲染器工作
对于不同的类型,渲染器底层会提供不同的类
- instantiateComponent: 根据传入对象的type创建不同的渲染器实例,比如,如果是一个文本,对应浏览器环境中的ReactDOMTextComponent
-
示例
渲染以下的react元素
class App extends React.component {
render() {
return (
<div>
<h1>Welcome Page</h1>
<Welcome name="Yaphet" />
</div>
)
}
}
class Welcome extends React.Component {
render(){
return (
<h2>{this.props.name}</h2>
)
}
}
ReactDOM.render(<App/>, document.getElementById("container"))
- 把给ReactDOM的render方法
- 将对应的渲染器实例化出来(ReactCompositeComponent)得到App节点(最上方)
- App节点根据元素的type(组合类型type为函数构造器)创建实例并运行render方法,得到了里面的第一个元素
- 拿到div之后创建相应的渲染器(ReactDOMComponent)并渲染这个原子类型的元素成为一个真实的dom节点
- 拿到里面的元素之后,分别实例化渲染器,再渲染出DOM元素
。。。。。。
依次按树🌲形向下。。。。。。
😍总结:在浏览器端,通过DOM API 完成UI的创建
浏览器端,js可以通过调用DOM API完成UI的创建,那js在Native端如何完成UI的创建呢?🧐
Native端如何创建视图
JavaScript 引擎
- 创建JavaScript上下文
JSContext *context = [[JSContext alloc] init]
- 在上下文中执行代码
[context evaluateScript:@"var triple = function(value) { return value + 3 }"];
- Native调用JavaScript
JSValue *tripleFn = context[@"triple"]
JavaScript把函数或变量暴露在全局,Native端就可以取到,同理,JS要用Native的东西,Native也必须把这个函数和变量暴露在全局
React Native实现JS Native互相调用
但在reactive native中 ,为了避免模块越来越多,会污染全局上下文
React Native只暴露了一个对象_fbBatchedBridge, 里面有一个方法callFunctionReturnFlushedQueue, 当Native调用js模块的时候,Native可以通过这个全局对象的方法,将想要调用模块的名称和方法的名称以及参数传进去,通过这个方法调用具体的模块
相反,Js调用native模块的时候,也通过一个中间方法调用相应的模块
ReactNative 中 js创建Native UI
调用UI Manager模块createView方法,传入相应的参数,创建客户端的视图
💡样式在ReactNative里面是通过对象表示的,将key/value传给Native端,让Native端解析这个对象,来渲染视图
😍总结:首先通过js引擎,调到Native端的代码,在Native端,UI manager创建对应视图