react构建小程序框架及remax的工作原理
发表时间:2021-1-11
发布人:葵宇科技
浏览次数:73
1、为什么要用 React 来构建小程序?
- react生态体系完善。
自Facebook在2013年5月开源React,经历了7年多的发展,react的社区生态体系非常庞大,若是使用react来构建小程序,那么在小程序开发中可以充分利用 React 生态体系中大量的技术沉淀(比如:react-use、field-form)。
- 更完整的 TypeScript 支持。
(1)当然也可以用 TypeScript 去写现有的小程序,但是由于小程序的架构原因(在小程序中,模版层和逻辑层是分开的,分别运行在渲染线程和逻辑线程),模板层跟逻辑层有天然的割裂,即使在逻辑层使用了 TypeScript,在模板层也无法享受类型检查和自动补全带来的便利。
(2)引入 React 后,我们的代码全部运行在逻辑层中,可以全程静态类型护航,给你满满的安全感。
2、使用react构建小程序的框架有哪些?
1、nanachi(娜娜奇):去哪儿
2、taro: 京东
3、remax: 阿里蚂蚁金服
4、Rax: 淘宝
3、现有的方案
静态编译
目前社区中使用 React 构建小程序的方案大都使用静态编译的方式实现。
所谓静态编译: 就是使用工具把代码语法分析一遍,把其中的 JSX 部分和逻辑部分抽取出来,分别生成小程序的静态模板和 小程序页面的定义。
静态编译来构建小程序的缺陷:
js动态写法,无法编译,需规避很多的动态写法。
因为语法分析是静态的,所以这些方案都会去限制一些动态的写法。另外正是因为 JavaScript 语言的动态性,要去做语法分析本身就是件很复杂的事情,所以这些方案实现起来往往也非常复杂。
例子:含有动态语法无法正确编译的case
- 运行时并没有 React 的存在,实际运行的是静态编译转换之后的小程序代码。
4、remax的实现方案及工作原理
Remax 让你可以使用真正的 React 去构建小程序,你可以把他理解成面向小程序的 React Native。
先看下react的架构:
- 最下面一层是 React 本身,上层的 ReactDOM 和 ReactNative等,也就是所说的render层。
- Renderer层跟 React 之间通过渲染器(ReactReconciler )连接,渲染器的作用就是把React 的虚拟 DOM 映射到对应平台的真实元素上去,(譬如:react-dom 的作用就是把虚拟 DOM 映射到浏览器的真实 DOM 上)。
- Remax实际上就是实现了一个面向小程序的渲染器,它把「虚拟 DOM」渲染到了小程序的视图层上。
问题:小程序没有DOM结构,remax是如何把虚拟DOM渲染到小程序的视图上的呢?
remax工作流程:
(1)在remax运行时,会通过渲染器将react中的组件渲染成Vnode结构,然后会调用节点上的 toJSON 方法,把这个 VNode 变成一个 JSON 对象,这个JOSN对象会被作为小程序页面page的data数据。
Vnode是什么?
VNode 就是 DOM 替代品,所以他长得也很像 DOM 元素,上面会有节点的类型(小程序中基础组件如:view、image、text),节点的属性和子节点,另外会有新增、删除和插入节点的方法.
import React from 'react';
import { View, Text } from 'remax/alipay';
const IndexPage = () => {
return (
<View className="greeting">
<Text>Hello Remax</Text>
</View>
);
};
export default IndexPage;
{
"id": 0,
"type": "root",
"children": [
{
"id": 1,
"type": "view",
"props": {
"className": "greeting"
},
"children": [
{
"id": 2,
"type": "text",
"props": {},
"children": [
{
"type": "plain-text",
"text": "Hello Remax"
}
]
}
]
}
]
}
(2)remax会使用脚手架工具remax-cli 来构建我们的代码 ,这个构建过程会生成一个能遍历 data数据的模板。
这个模板会先去遍历 data 根节点下的所有子元素,然后根据子元素的类型,使用其对应的模板来渲染这个节点。
利用模板递归渲染 data 的过程,也就把 React 运行到了小程序中并渲染出了界面。
// 模版
<block a:for="{{root.children}}" a:key="{{item.id}}">
<template is="{{'REMAX_TPL_' + item.type}}" data="{{item: item}}" />
</block>
// view类型模版
<template name="REMAX_TPL_view">
<view class="{{item.props['className']}}">
<block a:for="{{item.children}}" key="{{item.id}}">
<template is="{{'REMAX_TPL_' + item.type}}" data="http://www.wxapp-union.com/{{item: item}}" />
</block>
</view>
</template>
<template name="REMAX_TPL_text">
<text>
<block a:for="{{item.children}}" key="{{item.id}}">
<template is="{{'REMAX_TPL_' + item.type}}" data="http://www.wxapp-union.com/{{item: item}}" />
</block>
</text>
</template>
<template name="REMAX_TPL_plain-text">
<block>{{item.text}}</block>
</template>
小结:
remax来构建小程序的思路,没有借助重新打造react的轮子以及使用静态编译分析语法的方式,将react编译成运行需要的小程序语言。
remax的方案实现:
我觉得主要还是借鉴了react的架构和RN的实现思路,从某种程度上来说,remax其实就是面向小程序的RN,只不过这个面向小程序的实现不能使用RN的渲染器,而是remax开发的面向小程序的渲染器。
remax的亮点:
- Vnode层的引入
- Vnode转换成JSON的页面数据
- 面向小程序的渲染器
remax的工作原理:
(1)引入了Vnode层,通过渲染器将react的虚拟DOM渲染成了Vnod结构树。
(2)然后会调用节点上的 toJSON 方法,把这个 VNode 变成一个 JSON 对象。
(3)这个JSON对象会作为小程序页面的Data数据。
(4)在使用reamx-cli构建我们的代码时,构建过程会生成一个能遍历 data 的模板,在遍历的过程中,会根据元素的类型type去匹配对应的页面模版template,这个递归遍历的过程,通过使用对应的模版来承接data的数据展示,最终将data中数据展现在页面上。