小編給大家分享一下微信小程序中如何增加mixin擴(kuò)展,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
目前創(chuàng)新互聯(lián)建站已為上千多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁(yè)空間、成都網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、烏什網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
Mixin是一種思想,用部分實(shí)現(xiàn)的接口來(lái)實(shí)現(xiàn)代碼復(fù)用。可以用來(lái)解決多繼承的問(wèn)題,又可以用來(lái)擴(kuò)展功能。
Mixin簡(jiǎn)介
Mixin(織入)模式并不是GOF的《設(shè)計(jì)模式》歸納中的一種,但是在各種語(yǔ)言以及框架都會(huì)發(fā)現(xiàn)該模式(或者思想)的一些應(yīng)用。簡(jiǎn)單來(lái)說(shuō),Mixin是帶有全部實(shí)現(xiàn)或者部分實(shí)現(xiàn)的接口,其主要作用是更好的代碼復(fù)用。
Mixin這個(gè)概念在React, Vue中都有支持,它為我們抽象業(yè)務(wù)邏輯,代碼復(fù)用提供了方便。然而小程序原生框架并沒(méi)直接支持Mixin。我們先看一個(gè)很實(shí)際的需求:
為所有小程序頁(yè)面增加運(yùn)行環(huán)境class,以方便做一些樣式hack。具體說(shuō)就是小程序在不同的運(yùn)行環(huán)境(開(kāi)發(fā)者工具|iOS|Android)運(yùn)行時(shí),platform值為對(duì)應(yīng)的運(yùn)行環(huán)境值("ios|android|devtools")
<view class="{{platform}}">
<!--頁(yè)面模板-->
</view>回顧vue中mixin的使用
文章開(kāi)始提到的問(wèn)題是非常適合使用Mixin來(lái)解決的。我們把這個(gè)需求轉(zhuǎn)換成一個(gè)Vue問(wèn)題:在每個(gè)路由頁(yè)面中增加一個(gè)platform的樣式class(雖然這樣做可能沒(méi)實(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è)路由頁(yè)的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會(huì)有具體的合并,執(zhí)行策略。如下圖:

如何讓小程序支持mixin
在前面,我們回顧了vue中mixin的相關(guān)知識(shí)。現(xiàn)在我們要讓小程序也支持mixin,實(shí)現(xiàn)vue中一樣的mixin功能。
實(shí)現(xiàn)思路
我們先看一下官方的小程序頁(yè)面注冊(cè)方式:
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配置,上面的官方注冊(cè)方式會(huì)變成:
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) - 通過(guò)configObj配置小程序頁(yè)面的data, method, lifecycle等
onLoad方法 - 頁(yè)面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ò)展,測(cè)試可以參看github
/**
* 為每個(gè)頁(yè)面提供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));
}
// 頁(yè)面堆棧
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放入頁(yè)面堆棧
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方法會(huì)被丟棄
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ù)組存儲(chǔ)
ret[key] = ret[key].concat(mixin[key]);
} else {
ret[key] = [mixin[key]];
}
}
})
});
return ret;
};
/**
* 重復(fù)沖突處理借鑒vue:
* data, methods會(huì)合并,組件自身具有最高優(yōu)先級(jí),其次mixins中后配置的mixin優(yōu)先級(jí)較高
* lifecycle不會(huì)合并。先順序執(zhí)行mixins中的lifecycle,再執(zhí)行組件自身的lifecycle
*/
const mixData = (minxinData, nativeData) => {
Object.keys(minxinData).forEach(key => {
// page中定義的data不會(huì)被覆蓋
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會(huì)合并,組件自身具有最高優(yōu)先級(jí),其次mixins中后配置的mixin優(yōu)先級(jí)較高。
lifecycle不會(huì)合并。先順序執(zhí)行mixins中的lifecycle,再執(zhí)行組件自身的lifecycle。
以上是“微信小程序中如何增加mixin擴(kuò)展”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
分享名稱:微信小程序中如何增加mixin擴(kuò)展
URL地址:http://www.chinadenli.net/article8/jdgcop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供、網(wǎng)站維護(hù)、App開(kāi)發(fā)、App設(shè)計(jì)、網(wǎng)站營(yíng)銷、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)