导语: 以前在开发Native页面的同时,还处理Hybrid页面中Web和Native的交互,现在又开始接入Weex这样的跨平台开发方案,感觉纯粹的Native App离我们越来越远(感慨一下)。Weex到怎么工作的,本文简单说一下。【想知道如何将Weex接入iOS项目,请看Weex 1:Weex接入iOS项目)】
一、Weex架构
从Weex的架构图中可以看出
1、Weex首先将编写的Weex源码,也就是后缀名为.we,由<template>、<style> 和 <script>等标签组织好的内容,通过transformer(转换器,weex-toolkit 提供的工具)转换成JS Bundle。
2、然后将JS Bundle部署在服务器,当接收到终端(Web端、iOS端或Android端)的JS Bundle请求,将JS Bundle下发给终端。
3、在终端(Web端、iOS端或Android端)中,由Weex的JS Framework 接收和执行JS Bundle代码,并且执行数据绑定、模板编译等操作,然后输出JSON 格式的 Virtual DOM;JS Framework发送渲染指令给Native ,提供 callNative 和 callJS 接口,方便 JS Framework 和 Native 的通信。
说明:Weex源码转换成JS Bundle 、JS Framework 和Native渲染绝对是实现跨平台技术的关键(目前我是这么想的)。
二、Weex源码转换成JS Bundle
整体工作可以分为三个部分
1、转换 <template> 为 类JSON的树状数据结构, 转换数据绑定 为 返回数据的函数原型。#####
<foo a="{{x}}" b="1" /> --> {type: "foo", attr: {a: function () {return this.x}, b: 1}}.
2、转换 <style> 为 类JSON的树状数据结构。
.classname {name: value;} --> { classname : { name : value } }.
3、 把上面两部分的内容和 <script> 中的内容结合成一个JavaScript AMD(AMD:异步模块规范) 模块。#####
下面是一个完整的例子
<template>
<foo a="{{x}}" b="1" class="bar"></foo>
</template>
<style>
.bar {width: 200; height: 200}
</style>
<script>
module.exports = {
data: function () {
return {x: 100}
}
}
</script>
将转换为:
define('@weex-component/main', function () {
module.exports = {
data: function () {
return {x: 100}
}
}
module.template = {
type: "foo",
attr: {
a: function () {return this.x},
b: 1,
classname: ['bar']
}
}
module.style = {
bar: {width: 200, height: 200}
}
})
bootstrap('@weex-component/main')
说明1:除此之外,转换器还会做一些额外的事情: 合并Bundle ,添加引导函数,配置外部数据等等。
说明2:案例来自Weex的官方文档。当前大部分Weex工具最终输出的JS Bundle格式都经过了Webpack的二次处理,所以你实际使用工具输出的JS Bundle会和上面的有所区别。
三、JS Framework
1、JS Framework 简述#####
在初始化阶段被原生 JavaScript 引擎运行。它提供被每个JS Bundle调用的 define() 和 bootstrap() 函数。一旦JS Bundle从服务器下载后,这些函数就会执行. define() 函数以注册模块; bootstrap()会编译主要的模块为Virtual DOM,并发送渲染指令给Native 。就这样,同样的一份JSON 数据,在不同平台的渲染引擎中能够渲染成不同版本的 UI,这是 Weex 可以实现动态化的原因。
2、在Weex实例运行期间,Native和JS之间的相互调用的循环往复的调用会从Weex实例初始化持续到销毁#####
- callNative 是一个由native代码实现的函数, 它被JS代码调用并向native发送指令,例如 rendering, networking, authorizing和其他客户端侧的 toast 等API。
- callJS 是一个由JS实现的函数, 它用于Native向JS发送指令. 目前这些指令由用户交互和Native的回调函数组成。
四、Native渲染
1、Native 渲染引擎提供客户端组件(Component)和模块(Module)#####
组件(Component):在屏幕内可见,有特定行为,能被配置不同的属性和样式,能响应用户交互,常见的组件有: <div>、<text>、 <image>。
模块(Module): 是一组能被JS Framework调用的API. 其中的一些能以异步的方式调用JS Framework, 例如: 发送HTTP请求。
2、Weex 的渲染流程#####
Weex 的渲染流程如下图:
从Weex 渲染流程图中,可以看到渲染分为:
输入:虚拟DOM
构造树结构. 分析虚拟DOM JSON数据以构造渲染树(RT).
添加样式. 为渲染树的各个节点添加样式.
创建视图. 为渲染树各个节点创建Native视图.
绑定事件. 为Native视图绑定事件.
CSS布局. 使用 css-layout 来计算各个视图的布局.
更新视窗(Frame). 采用上一步的计算结果来更新视窗中各个视图的最终布局位置.
输出:Native UI 页面
End
本文参考:Weex 工作原理
更细致的内容深入在使用Weex之后再继续深入理解(毕竟第一次用)。