本文寫作時間為11月份,所以僅供參考其中的思路,如有與最新版本內(nèi)容不符者,以最新版本官方文檔為主;在大概 8 月底(2016年),有幸參與了企鵝 FM 和微云的微信小程序開發(fā),這篇文章是我對 UI 邏輯分 ...
在大概 8 月底(2016年),有幸參與了企鵝 FM 和微云的微信小程序開發(fā),這篇文章是我對 UI 邏輯分離的思考總結,另由于微云的業(yè)務邏輯代碼實在太復雜勒……所以文章中將主要以 FM 為例。
在微云和企鵝 FM 項目中我們都是采用 UI 工程師+前臺工程師的模式,所以必然出現(xiàn)了我們(總是吐槽的)在日常頁面開發(fā)中會采用的方式:
在 html/wxml 結構中用注釋的方式,告訴開發(fā) GG:“當出現(xiàn) XXX 情況的時候,加上 YYY class”,于是業(yè)務邏輯代碼中,就一定會摻雜著 UI 邏輯,甚至 hard code 的地方:
FM 中不止一種場景會觸發(fā)“播放”/”暫停”邏輯的應用,也就是有多種可能會觸發(fā) UI 的變化,那么 UI 邏輯還會有重復的地方。萬一有一天需要更換或新增或刪除 class 名,就很有可能出錯。
如果可以把 UI 邏輯獨立處理就好了,這是當時我的想法。經(jīng)過合作的開發(fā) GG 提點之后,由于很多 UI 層的邏輯是跟著業(yè)務邏輯走的,所以完全剝離 UI 邏輯是不現(xiàn)實的。強行分離就需要把this
傳來傳去,在我看來也不是回事兒。所以 UI 邏輯采用的還是單純的“變量分離”,可以粗暴理解為,把當時寫在注釋里的內(nèi)容,寫到獨立的 js 文件中。
下面以 FM 為例,來看看我是怎么做的吧~ FM 中 UI 會出現(xiàn)變化的是以下幾種場景:
因為小程序不支持 background-image
,所有圖片需要通過 <image>
組件現(xiàn)實,圖片的切換可以通過換不同的 src
值實現(xiàn)。
播放器有兩種顯示模式:mini 播放器和全屏播放器
這兩種模式是通過在播放器上切換 .mini
class(mini 狀態(tài)需要 .mini
)實現(xiàn)
全屏播放器的播放按鈕有“播放”和“暫停”兩種狀態(tài)(圖片)切換
當播放器進入全屏模式后,節(jié)目列表將被隱藏;而到 mini 播放器時,節(jié)目列表將重新顯示出來
列表中的節(jié)目,播放按鈕有“播放”和“暫停”兩種狀態(tài)切換
同 2,通過切換 src
值實現(xiàn)(這里應該也可以用 wx:if
來實現(xiàn))。
項目結構如下,其中在 utils
目錄中的 view.js
是 UI 邏輯部分的代碼:
pages
目錄中的 js 文件將通過 require
引用 view.js
,view.js
中的接口分為“通用”和“頁面使用”這兩個類型。
module.exports = {
// 通用
general: {
hide: 'hide',
show: 'show',
getScreenHeight: getScreenHeight
},
// 播放器頁面
playerView : {
class: {
mini: 'mini', // 小播放器模式要有這個 class
listItemPlaying: 'playing'
},
images: {
listPlayBtn: '../../images/play/play-list.png',
listPauseBtn: '../../images/play/pause-list.png',
playerPlayBtn: '../../images/play/play-player.png',
playerPauseBtn: '../../images/play/pause-player.png'
}
}
// 其他頁面如果也有需要,以頁面為單位添加...
}
在上面的代碼中,可以看到 general
里暴露了一個 getScreenHeight
方法,它用于獲取屏幕高度,我們在 onLoad
的時候通過它,將設置了背景色的結構的 min-height
屬性值設為屏幕高。用 js 的原因是,開發(fā)者工具 0.10 把 <page>
的高度 100% 去掉了,所以在 wxss 中就不能設置 height: 100%
把屏幕高度繼承下來,但我們又要保證在頁面資源加載出來以前,用戶看到的就是全屏的暗色背景。
在頁面使用的接口里就分成了 class
和 images
,如果未來出現(xiàn)更多 UI 變化的場景,可以再通過變量添加上去,比如 pageView.id
。
舉個超級簡單的例子(如下),模擬工作流程:
在 wxss 中定義好控制不同樣式的 class
將需要變化的 class 寫到 view.js
中,并暴露接口
在 wxml 中的對應結構中綁定 event handler
在對應的 page.js
里實現(xiàn) event handler 的具體內(nèi)容,也就是切換 class 的觸發(fā)條件
老司機一看就知道是 MVVM 模式。
這樣分離也就是為了 UI 有獨立的控制器,不至于和業(yè)務邏輯耦合嚴重,在頁面開發(fā)的階段就可以完成 UI 上的變化。之前寫網(wǎng)頁的時候,當需要 UI 變化的時候,我們常常會在頁面上綁定事件,示意前臺GG 邏輯是怎么樣的,但是那部分代碼可能并不能直接放入他們的業(yè)務邏輯中(可能是規(guī)范、邏輯沒有考慮完整……原因)。從這個角度上看,小程序反而能給 UI 工程師更多控制 UI 邏輯的能力,確定好代碼規(guī)范和接口,也能方便前臺 GG 直接使用 UI 代碼,專心業(yè)務邏輯~