Weex 2:浅说Weex工作原理

0.226字数 1176阅读 4351

导语: 以前在开发Native页面的同时,还处理Hybrid页面中Web和Native的交互,现在又开始接入Weex这样的跨平台开发方案,感觉纯粹的Native App离我们越来越远(感慨一下)。Weex到怎么工作的,本文简单说一下。【想知道如何将Weex接入iOS项目,请看Weex 1:Weex接入iOS项目)】

一、Weex架构

Weex架构图.png

从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。
JS调用Native.png
  • callJS 是一个由JS实现的函数, 它用于Native向JS发送指令. 目前这些指令由用户交互和Native的回调函数组成。
Native调用JS.png

四、Native渲染

1、Native 渲染引擎提供客户端组件(Component)和模块(Module)#####
  • 组件(Component):在屏幕内可见,有特定行为,能被配置不同的属性和样式,能响应用户交互,常见的组件有: <div>、<text>、 <image>。

  • 模块(Module): 是一组能被JS Framework调用的API. 其中的一些能以异步的方式调用JS Framework, 例如: 发送HTTP请求。

2、Weex 的渲染流程#####

Weex 的渲染流程如下图:

Weex渲染流程.png

从Weex 渲染流程图中,可以看到渲染分为:

输入:虚拟DOM

  • 构造树结构. 分析虚拟DOM JSON数据以构造渲染树(RT).

  • 添加样式. 为渲染树的各个节点添加样式.

  • 创建视图. 为渲染树各个节点创建Native视图.

  • 绑定事件. 为Native视图绑定事件.

  • CSS布局. 使用 css-layout 来计算各个视图的布局.

  • 更新视窗(Frame). 采用上一步的计算结果来更新视窗中各个视图的最终布局位置.

输出:Native UI 页面

End

本文参考:Weex 工作原理
更细致的内容深入在使用Weex之后再继续深入理解(毕竟第一次用)。

推荐阅读更多精彩内容