Do Not Repeat Yourself小程序
如何提升代碼質量,方法有許多:抽象、模塊、組件化,我認爲它們的中心點都是——Do Not Repeat Yourself.微信小程序
咱們先看看小程序自帶的組件化能力:微信
<import src="../name.wxml" />
引入 ---- success@import 'name.wxss'
引入 ---- success咱們看到,微信小程序開發有一個很大的痛點,缺少組件化能力,特別是在沒有使用構建工具或第三方框架的狀況下,稍不留神,就會充滿大量重複的代碼。框架
小程序提供了自定義組件( V1.6.3 才支持)xss
舉個栗子。ide
小程序雖然提供了一些經常使用的組件——toast、loading等,但因需求不一樣,咱們要實現本身的 popup
、notify
、modal
等公共組件。這些自定義組件的共同點是:單個組件模板、事件大體同樣,區別是每次使用組件時顯示的內容不一樣。因而,咱們在每一個頁面都能看到類似的代碼,emm,已經產生了臭味道。函數
經過混入的方式,將組件方法、數據綁定到頁面實例上,相似VUE mixins
,不過,這裏實現要更爲簡單:工具
function mixins(page, ...args) { let data = args.reduce((res, item) => Object.assign(res, item.data), page.data || {}) Object.assign(page, ...args) page.setData(data) }
這樣,在頁面onLoad
時,執行mixins(this, Component1, ...)
就能夠了。組件化
如今開始寫一個 popup
組件,設計給的樣式以下圖:
佈局
除去佈局和樣式,應該如何設計數據模型?我的認爲須要把握兩點:職責分離、易於擴展。
可變數據:標題、內容、按鈕文字、按鈕個數、點擊按鈕後續操做、蒙層是否可點
不變數據:點擊蒙層、取消按鈕隱藏popup,顯示/隱藏popup事件
經過第一步的分析,咱們能夠拋開具體的業務邏輯,設計出popup
的數據模型:
let popupModal = { title: '', content: '', confirmButtonName: '確認', cancelButtonName: '取消', show(), hide(), onConfirm(), onCancel(), }
使用面向對象能夠輕鬆分離可變、不可變數據,生成所需數據模型:
class GeneratePopupModal { constructor(options) { this.setParams(options) } setParams({ title, content, confirmButtonName, cancelButtonName, success, } = {}) { this.title = title || this.title this.content = content || this.content this.confirmButtonName = confirmButtonName || this.confirmButtonName this.cancelButtonName = cancelButtonName || this.cancelButtonName this.success = success } show() { return Promise.resolve(this.__show = true) } hide() { return Promise.resolve(this.__show = false) } onConfirm() { return this.hide() .then(() => { if(this.success) return this.success({confirm: true}) }) } onCancel() { return this.hide() .then(() => { if(this.success) return this.success({cancel: true}) }) } }
爲了使popup
組件保持簡單,只對外暴露三個方法:
const GeneratePopupModal = require('./generatePopupModal') const defalut = { title: '管家提示', content: '抱歉,咱們遇到一點問題,請稍後再試', confirmButtonName: '確認' } let Popup = null module.exports = { $popup(options={}) { /** * 每次使用新建實例,避免狀態共享 * 經過私有 __show 控制 popup.show,實現組件 popup 的顯示和隱藏 */ Popup = new GeneratePopupModal(defalut) Object.defineProperty(Popup, '__show', { configurable: true, set: v => { Popup.show = v this.setData({popupModal: Popup}) } }) return new Promise((resolve, reject) => { Popup.setParams( Object.assign({}, {success: resolve, fail: reject}, options) ) Popup.__show = true }) }, tapPopupConfirmButton() { Popup.onConfirm() }, tapPopupCancelButton() { Popup.onCancel() }, }
在上面mixins
部分,介紹瞭如何引入組件。那麼,怎麼使用它呢?這裏提供一個栗子:
this.$popup({ // 根據傳參生成數據、顯示 popup title: '刪除行程', content: '確認刪除此行程?刪除後將不可恢復。', confirmButtonName: '刪除', cancelButtonName: '我再想一想', }).then(({confirm, cancel}) => { // 分別表示點擊了肯定、取消按鈕 if(confirm) { // 點擊刪除(肯定)按鈕後續操做 return r4251({ id: item.productid, type: item.type }) .then(res => this.__fetchCartList()) .catch(e => { this.$popup() // 顯示默認數據的 popup console.error('[cart/list.js] #tapDeleteCart r4251 error: ', e) }) } })
至此,popup
組件基本完成了,但這種方式依然存在很大的漏洞:
雖然上面的解決方案並不十分理想~難道不是很是彆扭?~,但好在足夠簡潔、實用,也基本實現了設計預期。
期待更好的實現思路......
.