深入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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 轉載 :OpenDiggawesome-github-vue 是由OpenDigg整理并維護的Vue相關開源項目庫...
    果汁密碼閱讀 23,202評論 8 124
  • 來源:github.com Vue.js開源項目速查表:https://www.ctolib.com/cheats...
    zhangtaiwei閱讀 11,659評論 1 159
  • 前幾天工作遇到不可理喻的事情,很生氣,沒忍住的就在聊天框里和門店員工理論了幾句,估計當時如果是面對面就吵起來了,但...
    消失的書店閱讀 358評論 0 0
  • 當你迷茫的時候,你不應該為此而感到迷茫。 當你孤獨的時候,...
    ZZZyyyfffang閱讀 1,053評論 0 0
  • Day 1 火急火燎地趕到機場,往火爐奔去。 8點的重慶還亮著天,攜程約來的商務車帶我們穿過大佛寺長江大橋、五層立...
    月色的筆尖閱讀 548評論 0 0