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
组件基本完成了,但这种方式依然存在很大的漏洞:
虽然上面的解决方案并不十分理想~难道不是很是别扭?~,但好在足够简洁、实用,也基本实现了设计预期。
期待更好的实现思路......
.