您好,登錄后才能下訂單哦!
小編給大家分享一下微信小程序中如何增加mixin擴(kuò)展,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
Mixin是一種思想,用部分實(shí)現(xiàn)的接口來實(shí)現(xiàn)代碼復(fù)用??梢杂脕斫鉀Q多繼承的問題,又可以用來擴(kuò)展功能。
Mixin簡介
Mixin(織入)模式并不是GOF的《設(shè)計(jì)模式》歸納中的一種,但是在各種語言以及框架都會發(fā)現(xiàn)該模式(或者思想)的一些應(yīng)用。簡單來說,Mixin是帶有全部實(shí)現(xiàn)或者部分實(shí)現(xiàn)的接口,其主要作用是更好的代碼復(fù)用。
Mixin這個(gè)概念在React, Vue中都有支持,它為我們抽象業(yè)務(wù)邏輯,代碼復(fù)用提供了方便。然而小程序原生框架并沒直接支持Mixin。我們先看一個(gè)很實(shí)際的需求:
為所有小程序頁面增加運(yùn)行環(huán)境class,以方便做一些樣式hack。具體說就是小程序在不同的運(yùn)行環(huán)境(開發(fā)者工具|iOS|Android)運(yùn)行時(shí),platform值為對應(yīng)的運(yùn)行環(huán)境值("ios|android|devtools")
<view class="{{platform}}"> <!--頁面模板--> </view>
回顧vue中mixin的使用
文章開始提到的問題是非常適合使用Mixin來解決的。我們把這個(gè)需求轉(zhuǎn)換成一個(gè)Vue問題:在每個(gè)路由頁面中增加一個(gè)platform的樣式class(雖然這樣做可能沒實(shí)際意義)。實(shí)現(xiàn)思路就是為每個(gè)路由組件增加一個(gè)data: platform
。代碼實(shí)現(xiàn)如下:
// mixins/platform.js const getPlatform = () => { // 具體實(shí)現(xiàn)略,這里mock返回'ios' return 'ios'; }; export default { data() { return { platform: getPlatform() } } }
// 在路由組件中使用 // views/index.vue import platform from 'mixins/platform'; export default { mixins: [platform], // ... }
// 在路由組件中使用 // views/detail.vue import platform from 'mixins/platform'; export default { mixins: [platform], // ... }
這樣,在index,detail兩個(gè)路由頁的viewModel上就都有platform這個(gè)值,可以直接在模板中使用。
vue中mixin分類
data mixin
normal method mixin
lifecycle method mixin
用代碼表示的話,就如:
export default { data () { return { platform: 'ios' } }, methods: { sayHello () { console.log(`hello!`) } }, created () { console.log(`lifecycle3`) } }
vue中mixin合并,執(zhí)行策略
如果mixin間出現(xiàn)了重復(fù),這些mixin會有具體的合并,執(zhí)行策略。如下圖:
如何讓小程序支持mixin
在前面,我們回顧了vue中mixin的相關(guān)知識。現(xiàn)在我們要讓小程序也支持mixin,實(shí)現(xiàn)vue中一樣的mixin功能。
實(shí)現(xiàn)思路
我們先看一下官方的小程序頁面注冊方式:
Page({ data: { text: "This is page data." }, onLoad: function(options) { // Do some initialize when page load. }, onReady: function() { // Do something when page ready. }, onShow: function() { // Do something when page show. }, onHide: function() { // Do something when page hide. }, onUnload: function() { // Do something when page close. }, customData: { hi: 'MINA' } })
假如我們加入mixin配置,上面的官方注冊方式會變成:
Page({ mixins: [platform], data: { text: "This is page data." }, onLoad: function(options) { // Do some initialize when page load. }, onReady: function() { // Do something when page ready. }, onShow: function() { // Do something when page show. }, onHide: function() { // Do something when page hide. }, onUnload: function() { // Do something when page close. }, customData: { hi: 'MINA' } })
這里有兩個(gè)點(diǎn),我們要特別注意:
Page(configObj)
- 通過configObj配置小程序頁面的data, method, lifecycle等
onLoad方法 - 頁面main入口
要想讓mixin中的定義有效,就要在configObj正式傳給Page()
之前做文章。其實(shí)Page(configObj)
就是一個(gè)普通的函數(shù)調(diào)用,我們加個(gè)中間方法:
Page(createPage(configObj))
在createPage這個(gè)方法中,我們可以預(yù)處理configObj中的mixin,把其中的配置按正確的方式合并到configObj上,最后交給Page()
。這就是實(shí)現(xiàn)mixin的思路。
具體實(shí)現(xiàn)
具體代碼實(shí)現(xiàn)就不再贅述,可以看下面的代碼。更詳細(xì)的代碼實(shí)現(xiàn),更多擴(kuò)展,測試可以參看github
/** * 為每個(gè)頁面提供mixin,page invoke橋接 */ const isArray = v => Array.isArray(v); const isFunction = v => typeof v === 'function'; const noop = function () {}; // 借鑒redux https://github.com/reactjs/redux function compose(...funcs) { if (funcs.length === 0) { return arg => arg; } if (funcs.length === 1) { return funcs[0]; } const last = funcs[funcs.length - 1]; const rest = funcs.slice(0, -1); return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args)); } // 頁面堆棧 const pagesStack = getApp().$pagesStack; const PAGE_EVENT = ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage']; const APP_EVENT = ['onLaunch', 'onShow', 'onHide', 'onError']; const onLoad = function (opts) { // 把pageModel放入頁面堆棧 pagesStack.addPage(this); this.$invoke = (pagePath, methodName, ...args) => { pagesStack.invoke(pagePath, methodName, ...args); }; this.onBeforeLoad(opts); this.onNativeLoad(opts); this.onAfterLoad(opts); }; const getMixinData = mixins => { let ret = {}; mixins.forEach(mixin => { let { data={} } = mixin; Object.keys(data).forEach(key => { ret[key] = data[key]; }); }); return ret; }; const getMixinMethods = mixins => { let ret = {}; mixins.forEach(mixin => { let { methods={} } = mixin; // 提取methods Object.keys(methods).forEach(key => { if (isFunction(methods[key])) { // mixin中的onLoad方法會被丟棄 if (key === 'onLoad') return; ret[key] = methods[key]; } }); // 提取lifecycle PAGE_EVENT.forEach(key => { if (isFunction(mixin[key]) && key !== 'onLoad') { if (ret[key]) { // 多個(gè)mixin有相同lifecycle時(shí),將方法轉(zhuǎn)為數(shù)組存儲 ret[key] = ret[key].concat(mixin[key]); } else { ret[key] = [mixin[key]]; } } }) }); return ret; }; /** * 重復(fù)沖突處理借鑒vue: * data, methods會合并,組件自身具有最高優(yōu)先級,其次mixins中后配置的mixin優(yōu)先級較高 * lifecycle不會合并。先順序執(zhí)行mixins中的lifecycle,再執(zhí)行組件自身的lifecycle */ const mixData = (minxinData, nativeData) => { Object.keys(minxinData).forEach(key => { // page中定義的data不會被覆蓋 if (nativeData[key] === undefined) { nativeData[key] = minxinData[key]; } }); return nativeData; }; const mixMethods = (mixinMethods, pageConf) => { Object.keys(mixinMethods).forEach(key => { // lifecycle方法 if (PAGE_EVENT.includes(key)) { let methodsList = mixinMethods[key]; if (isFunction(pageConf[key])) { methodsList.push(pageConf[key]); } pageConf[key] = (function () { return function (...args) { compose(...methodsList.reverse().map(f => f.bind(this)))(...args); }; })(); } // 普通方法 else { if (pageConf[key] == null) { pageConf[key] = mixinMethods[key]; } } }); return pageConf; }; export default pageConf => { let { mixins = [], onBeforeLoad = noop, onAfterLoad = noop } = pageConf; let onNativeLoad = pageConf.onLoad || noop; let nativeData = pageConf.data || {}; let minxinData = getMixinData(mixins); let mixinMethods = getMixinMethods(mixins); Object.assign(pageConf, { data: mixData(minxinData, nativeData), onLoad, onBeforeLoad, onAfterLoad, onNativeLoad, }); pageConf = mixMethods(mixinMethods, pageConf); return pageConf; };
小結(jié)
1、本文主要講了如何為小程序增加mixin支持。實(shí)現(xiàn)思路為:預(yù)處理configObj
Page(createPage(configObj))
2、在處理mixin重復(fù)時(shí),與vue保持一致:
data, methods會合并,組件自身具有最高優(yōu)先級,其次mixins中后配置的mixin優(yōu)先級較高。
lifecycle不會合并。先順序執(zhí)行mixins中的lifecycle,再執(zhí)行組件自身的lifecycle。
以上是“微信小程序中如何增加mixin擴(kuò)展”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。