小程序對組件化的「支持」狀況小程序對組件化的「支持」狀況:css
微信小程序(如下簡稱「小程序」,版本)雖然默認定義了不少有用的組件,可是在開發小程序過程當中,每每須要自定義業務組件。
而小程序開發者文檔中卻未對自定義組件給出很好的解決方案或示例。
猜其緣由可能有兩方面:web
微信的組件化,整體而言,目標就是把具備特定功能和樣式的wxml、wxss、js(可選)文件抽取出來,以便不一樣頁面之間進行復用。
咱們從實現上來考慮是否可行:json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// tab component - |- tab.wxml |- tab.js |- tab.wxss // tab.wxss .tab { ... } .tab .itme { ... } ... |
由於咱們採用了include的方式共享了做用域,在簡單頁面的狀況這種方式也不會出現什麼問題,若是變量名或事件名被佔用的時候換一個就行了。
可是在頁面引用多個組件的狀況下如何保證它們之間不產生衝突?你可能想到了用老辦法命名隔離,組件內部變量和事件添加組件前綴用來和其它組件區分。
OK,在組件名不重複的狀況下這是可行的。可是若是一個組件要同時觸發自身內部事件和父頁面事件就不是這麼簡單了。
因此咱們須要解決的一個關鍵問題是:組件如何隔離做用域,並暴露屬性或接口(函數)給頁面或其它組件?小程序
咱們在探索組件化實現方式時,有一個第三方模塊wepy脫穎而出。star數量超過了1k,文檔清晰簡約。
看看它的主要功能:微信小程序
MVVM多用於web單頁應用,而小程序明顯不是單頁應用,並且也不支持雙數據綁定,轉爲MVVM方式更多隻是習慣上的喜愛,談不上什麼優勢。
小程序也支持ES6特性(之前也支持ES7,不知道爲何新版本取消了),用ES6特性能夠完成外部NPM包引用。微信
因此最吸引人的功能就是第二點:支持組件化。babel
拿到官方給的示例wepy-wechat-demo編譯後對比源碼和編譯後的代碼來探究其實現組件化的思路。xss
整個項目很是清晰簡單,咱們以index頁面調用tab組件爲例進行分析。函數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// src目錄 - |- components - tab.wpy ... |- pages - index.wpy ... // dist目錄 - dist |- components - tab.wxss - tab.js |- pages - index.js - index.json - index.wxml - index.wxss |
js文件用ES6編寫,經過babel轉成ES5形式,看起來比較費勁,不過幸虧咱們暫時也不須要分析它。打開index.wxss和tab.wxss能夠看到組件樣式的編寫和引用方式如咱們所料,經過微信的@import方式引入。工具
1 2 3 4 5 6 7 8 9 10 11 12 |
// dist/components/tab.wxss .tab { ... } .tab .item { ... } ... // dist/pages/index.wxss @import "./../components/tab.wxss"; ... |
很奇怪,在編譯好的components文件夾中只能看到組件命名的js和wxss文件,wxml文件消失了~
因此先來看看index.wxml中怎麼體現的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// dist/pages/index.wxml <view class="tab"> <view class="tab_item tab_message{{$tab$active == 0 ? ' active' : ''}}" bindtap="$tab$change" data-wepy-params-a="0"> <image class="icon" src="../images/message{{$tab$active == 0 ? '_active' : ''}}.png"/> <text class="title">微信</text> </view> ... </view> // src/components/tab.wxml <template> <view class="tab"> <view class="tab_item tab_message{{active == 0 ? ' active' : ''}}" @tap="change(0)"> <image class="icon" src="../images/message{{active == 0 ? '_active' : ''}}.png"></image> <text class="title">微信</text> </view> ... </view> </template> |
這段編譯後的代碼和tab.wxml源文件基本一致,發生改變的是數據綁定和事件綁定的地方,進行了重命名。
由此能夠推斷,是經過wepy的編譯工具wepy-cli,把頁面上的組件引用替換成了源碼並經過修改變命名來隔離組件做用域避免衝突。
而這些從新修改的變量和事件如何起做用?
wepy的文檔中提到組件支持回調和事件冒泡、事件下發,要支持這個特性除了按其要求的格式進行編寫以外,還須要在js中引用一個叫wepy的模塊,如
import wepy from 'wepy'
由此能夠推斷,wepy-cli編譯的時候進行了模板替換和變量名(事件名)替換,而後wepy模塊來處理替換後的事件調用以及組件之間的通訊。
若是仔細翻閱文檔會發現其對組件的支持很是接近Vue.js 2.x,好比computed、watcher屬性。行文此處,給做者由衷地點個贊。
那麼這種方式是否就是最理想的組件化方式,或者說這種方式有什麼缺陷呢?