微信小程式元件化(上)

亞里士朱德發表於2017-08-16

小程式對元件化的“支援”情況

微信小程式(以下簡稱“小程式”,版本)雖然預設定義了很多有用的元件,但是在開發小程式過程中,往往需要自定義業務元件。 而小程式開發者文件中卻未對自定義元件給出很好的解決方案或示例。 猜其原因可能有兩方面:

  1. 從小程式開放的API來看,它去除了DOM和BOM,檢視與資料層互動採用簡單的單向資料繫結和事件綁的形式。可能其初衷是想降低開發難度和學習門檻,儘量減少概念。
  2. 小程式推出時間不到一年,這些功能可能還在完善中。

自定義元件的難點

微信的元件化,總體而言,目標就是把具有特定功能和樣式的wxml、wxss、js(可選)檔案抽取出來,以便不同頁面之間進行復用。 我們從實現上來考慮是否可行:

  • wxss支援檔案之間的引用,採用命名隔離的話應該可以支援元件化的需求。即把不同元件拆成不同的wxss,通過一致的命名與元件的試圖、邏輯對應,同時元件樣式選擇器都掛載在跟樣式下。使用時記得引用該wxss就好。當然預編譯語言中所使用的變數、函式什麼的就不要想了~

  • wxml也支援引用,兩種方式:template和include。區別在於作用域。include相當於把程式碼拷貝到當前位置,與頁面共享作用域,而import擁有自己的獨立作用域,一般需要傳入對應的引數。看似template更適合,可是template的事件繫結卻仍是和父頁面共享作用域,也就是說資料在template獨立作用域中,事件繫結在頁面內作用域,兩者之間的相互引用就會變得相當尷尬,還不如include順暢。
  • 小程式支援ES6,所以我們可以用ES6的模組管理方式來引入對應的js檔案。
  • 因為json是針對於頁面進行的配置,元件關心的是區域性樣式和邏輯,所以元件化的時候我們並不需要它。

因為我們採用了include的方式共享了作用域,在簡單頁面的情況這種方式也不會出現什麼問題,如果變數名或事件名被佔用的時候換一個就好了。 但是在頁面引用多個元件的情況下如何保證它們之間不產生衝突?你可能想到了用老辦法命名隔離,元件內部變數和事件新增元件字首用來和其它元件區分。 OK,在元件名不重複的情況下這是可行的。但是如果一個元件要同時觸發自身內部事件和父頁面事件就不是這麼簡單了。 所以我們需要解決的一個關鍵問題是:元件如何隔離作用域,並暴露屬性或介面(函式)給頁面或其它元件?

元件化解決方案

第三方實現

我們在探索元件化實現方式時,有一個第三方模組wepy脫穎而出。star數量超過了1k,文件清晰簡約。 看看它的主要功能

  1. 將小程式開發模式轉為MVVM方式
  2. 支援類Vue.js 2.x風格的元件開發,包括單檔案元件,支援scss、pug等。
  3. 支援載入外部NPM包
  4. 使用babel編譯,支援ES6/ES7特性

MVVM多用於web單頁應用,而小程式明顯不是單頁應用,而且也不支援雙資料繫結,轉為MVVM方式更多隻是習慣上的喜好,談不上什麼優點。 小程式也支援ES6特性(以前也支援ES7,不知道為什麼新版本取消了),用ES6特性可以完成外部NPM包引用。

所以最吸引人的功能就是第二點:支援元件化。

拿到官方給的示例wepy-wechat-demo編譯後對比原始碼和編譯後的程式碼來探究其實現元件化的思路。

整個專案非常清晰簡單,我們以index頁面呼叫tab元件為例進行分析。

js檔案用ES6編寫,通過babel轉成ES5形式,看起來比較費勁,不過幸好我們暫時也不需要分析它。開啟index.wxss和tab.wxss可以看到元件樣式的編寫和引用方式如我們所料,通過微信的@import方式引入。

很奇怪,在編譯好的components資料夾中只能看到元件命名的js和wxss檔案,wxml檔案消失了~ 所以先來看看index.wxml中怎麼體現的

這段編譯後的程式碼和tab.wxml原始檔基本一致,發生改變的是資料繫結和事件繫結的地方,進行了重新命名。 由此可以推斷,是通過wepy的編譯工具wepy-cli,把頁面上的元件引用替換成了原始碼並通過修改變命名來隔離元件作用域避免衝突。 而這些重新修改的變數和事件如何起作用? wepy的文件中提到元件支援回撥和事件冒泡、事件下發,要支援這個特性除了按其要求的格式進行編寫之外,還需要在js中引用一個叫wepy的模組,如

import wepy from 'wepy'

由此可以推斷,wepy-cli編譯的時候進行了模板替換和變數名(事件名)替換,然後wepy模組來處理替換後的事件呼叫以及元件之間的通訊。

如果仔細翻閱文件會發現其對元件的支援非常接近Vue.js 2.x,比如computed、watcher屬性。行文此處,給作者由衷地點個zan。

那麼這種方式是否就是最理想的元件化方式,或者說這種方式有什麼缺陷呢?

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

微信小程式元件化(上) 微信小程式元件化(上)

相關文章