深入Weex中的transformer实现原理(上篇)

0x1 读完后希望你会

  • 了解Weex中,we脚本的各个标签<template><script><style>解析实现方式,如何生成可以运行的js脚本文件。
  • 基于标签tag,自己实现一套你喜欢的类似we或者微信小程序的脚本语言。
    • 可以包含表达式计算
    • 流程控制

0x2 背景

目前线上App接入的weex版本为0.8.X,距目前最新的0.10.X系列跨度相差较大,但是在保证目前业务稳定的前提下,不能直接升级Weex SDK到最新版。

在升级前期,不得不面对的几个问题:

  • 目前已开发的大量.we页面是否可以在新版Weex运行。
  • 继续使用已被废弃的we脚本开发新需求(Weex已经推荐用vue来写页面)
    • Vue与Weex两大生态的联手,Weex官方也在推进vue来编写界面.
    • we脚本将来很有可能面临不再被扩展维护,也就是weex很多的新特性在we中不一定会被支持,除非we与vue的feature更新节奏保持一致。
    • 据说手淘与猫客已不再使用we编写weex,而是全部采用vue(求证)。
    • Vue自身生态庞大,对vue更好的支持,反而更利于weex的推广。

所以在升级之前,以weex的transform流程原理为开端,展开一些前期的调研工作,顺便学习一下weex的toolkit实现原理。
据weex的同学说新版的weex是可以跑老we的,不过要保证we脚本代码的严谨性,因为新版的jsf runtime校验机制,更加严格,某些页面可能白屏(What?!!)。
老话常谈,“Talk is cheap,Show me the code”。

0x3 验证思路

一个we页面被渲染执行,可以大致拆分为两部分。
【.we脚本的打包与编译】(weex/vue loader,生成标准的js脚本)

    [.we] -> [build] -> output [*.js]

【Weex JS 运行时环境(JSF)】(负责解析运行编译好的js脚本)

    [*.js] -> [weex runtime] -> render [view:page]
Weex模块构成.png

从图中可以看出 Weex 整体的工作流程。
首先开发者编写 .we 文件。
通过 weex-toolkit 提供的工具将 .we 文件转为js。

JS Framework 接收并执行 js 的代码,执行数据绑定、模板编译等操作,然后输出 json 格式的 Virtual DOM 传递给移动端。

这篇文章主要分析第一层的transformer的实现原理。

0x4 we/vue 脚本是如何被解析的

不可不说的parse5:
weex-loader中,对we文件的解析主要依赖第三方开源npm组件,html标签解析的parse5,对输入的html标签类文本,解析后输出json对象。
关于输出的json格式,可以参考官方的在线playground,http://astexplorer.net/#/1CHlCXc4n4

weex-loader首先通过parse5 得到we文本的json 结构的树结构,
然后Weex-loader的处理流程中,针对不同标签(<template/> <script/><style/>),分别有对应的解析处理模块,

Paste_Image.png

大致流程如上图,从左向右依次为:
1.输入为原始we脚本文件。
2.通过parse5组件解析出对应的jsonobject
3.根据json object中描述的各部分tag交给对应的处理模块。

例如一个template标签的json对象,在loader中是这样被处理的,

Paste_Image.png

源码地址: weex-loader/lib/loader.js

不同的标签类型文本会分配给专门的parse组件.

Paste_Image.png

源码地址:weex-loader/lib/parser.js

标签对应的处理模块如下:
<script> 标签 ————> weex-templater
<style > 标签 ————> weex-styler
<script> 标签 ————> weex-scripter

0x5 weex-styler 简介以及CSS预备知识

weex-styler负责处理weex所支持的css样式,以及验证开发者所写的css样式是否正确。
其中实现原理是使用开源css https://www.npmjs.com/package/css 组件,根据css代码的文本段,生成json object类型的 ast节点信息。要了解weex-styler的处理流程,势必要了解一下ast以及css的基本概念。

一张图看懂CSS构成.

A CSS rule-set consists of a selector and a declaration block:

Paste_Image.png

rule-set:包含一个selector 以及多个declaration。
selector:样式选择器,主要用来定位元素
declaration:定义样式属性以及值。

了解这三个基本概念之后,看scripter也是轻车熟路了,快上车。
scripter当中,通过css parser得到AST json object,读取ast.stylesheet.rules获得到当前样式的rule-set,然后遍历所有的declaration,校验样式是否被weex所支持的(因为weex中支持css的样式有限),以及简单的value字段合法性校验。

![Uploading Paste_Image_374004.png . . .]

源码:/weex-styler/index.js

weex-styler新老版之差异。

对Pseudo class样式进行了支持。

Paste_Image.png

新版weex中,支持shorthand writing写法的transition样式。

// shorthand writing 
div {
    transition: width 2s linear 1s;
}

div {
    transition-property: width;
    transition-duration: 2s;
    transition-timing-function: linear;
    transition-delay: 1s;
}

0x6 weex-templater 简介

解析we脚本中的<template/>标签内容,其核心节点数据结构也是基于parse5解析出的json object,同时也会做数据绑定,标签验证,自动修复common错误的处理。

<template>
  <div if={{x}}>
    <text onclick="toggle">Toggle: {{result}}</text>
  </div>
</template>
  • 数据绑定:
    <text>标签内的value,”Toggle: {{result}}”,
    <div>标签内的attribute if 中的 “{{x}}”,
    也就这种用户可以编辑的文本段,需要对包含的表达式以及变量进行处理,这里的实现就在var exp = require('./exp’)这个模块当中,

该exp函数有2个参数,需要转换的字符串文本,以及是否需要转换成function对象。

![Uploading Paste_Image_402398.png . . .]

/weex-templater/lib/exp.js

将双引号“替换为单引号’,去除所有\n换行控制字符。
判断文本中是否包含表达式,如果不包含,直接返回原始文本。
根据生成的token列表,
文本会在两端加入单引号’
表达式在两端(),显式的加入运算优先级。
比如Toggle: {{result}} => [‘\’Toggle:\’’,’(result)’]
这样在最后,只需要把结果列表中的所有元素做一次’+’.join操作,就可以构成了一个合法的js语句。

  • 事件绑定:
    text中的onclick属性的值,templater会自动生成可以调用toggle函数的js代码。当标签的属性名包含on前缀时,将进行事件绑定。
Paste_Image.png

weex-templater/index.js

在checkEvent方法中,通过把封装好的function描述字符串eval对象赋值给value,达到事件发生时触发函数的机制。


  • 对template的内容,对元素标签(如<div/><a/><img/等>),控制语句(if,else,repeat等)做validation,针对不同标签,会有额外特殊的验证操作。

下面举几个典型例子,

  1. 【If】 validation: <if={{x == 1}}> 验证if中包含的value,以及value是否是一个合法的表达式。
Paste_Image.png
  1. 【else】 validation:当遍历到一个节点中包含else时,就会验证前一个节点中是否包含了if。
  2. Tag(标签)validation:
    Tag的验证相对多一点,因为不同的tag会有其特殊的规则,
    例如最外层的<template/>只能包含一个root子节点。
    container类型的标签可以嵌套标签,非container则不可。
    <cell>标签可以自动补全tree属性。
  3. <text>标签比较特殊,因为text里面可以包含任意的字符串,变量,表达式,
    例如下面的脚本。
  • 修复一些简单的common问题。
    举个例子,比如图像内容,既可以写成<img>也可以写成<Image>,在templater中是有处理的。

源码地址:weex-templater/lib/validator.js

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容