|
導讀微信小程序,簡稱小程序,英文名Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應用。小程序是一種不用下載就能使用的應用,也是一... 微信小程序,簡稱小程序,英文名Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應用。小程序是一種不用下載就能使用的應用,也是一項門檻非常高的創新,經過將近兩年的發展,已經構造了新的小程序開發環境和開發者生態。 這篇文章主要介紹了關于微信小程序開發教程之增加mixin擴展,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下Mixin是一種思想,用部分實現的接口來實現代碼復用。可以用來解決多繼承的問題,又可以用來擴展功能。下面這篇文章主要給大家介紹了關于為微信小程序增加mixin擴展的相關資料,需要的朋友可以參考借鑒,下面來一起看看吧。 Mixin簡介 Mixin(織入)模式并不是GOF的《設計模式》歸納中的一種,但是在各種語言以及框架都會發現該模式(或者思想)的一些應用。簡單來說,Mixin是帶有全部實現或者部分實現的接口,其主要作用是更好的代碼復用。 Mixin這個概念在React, Vue中都有支持,它為我們抽象業務邏輯,代碼復用提供了方便。然而小程序原生框架并沒直接支持Mixin。我們先看一個很實際的需求: 為所有小程序頁面增加運行環境class,以方便做一些樣式hack。具體說就是小程序在不同的運行環境(開發者工具|iOS|Android)運行時,platform值為對應的運行環境值("ios|android|devtools") <view class="{{platform}}">
<!--頁面模板-->
</view>回顧vue中mixin的使用 文章開始提到的問題是非常適合使用Mixin來解決的。我們把這個需求轉換成一個Vue問題:在每個路由頁面中增加一個platform的樣式class(雖然這樣做可能沒實際意義)。實現思路就是為每個路由組件增加一個 // mixins/platform.js
const getPlatform = () => {
// 具體實現略,這里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兩個路由頁的viewModel上就都有platform這個值,可以直接在模板中使用。 vue中mixin分類
用代碼表示的話,就如: export default {
data () {
return {
platform: 'ios'
}
},
methods: {
sayHello () {
console.log(`hello!`)
}
},
created () {
console.log(`lifecycle3`)
}
}vue中mixin合并,執行策略 如果mixin間出現了重復,這些mixin會有具體的合并,執行策略。如下圖:
如何讓小程序支持mixin 在前面,我們回顧了vue中mixin的相關知識。現在我們要讓小程序也支持mixin,實現vue中一樣的mixin功能。 實現思路 我們先看一下官方的小程序頁面注冊方式: 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'
}
})這里有兩個點,我們要特別注意:
要想讓mixin中的定義有效,就要在configObj正式傳給 Page(createPage(configObj)) 在createPage這個方法中,我們可以預處理configObj中的mixin,把其中的配置按正確的方式合并到configObj上,最后交給 具體實現 具體代碼實現就不再贅述,可以看下面的代碼。更詳細的代碼實現,更多擴展,測試可以參看github /**
* 為每個頁面提供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]) {
// 多個mixin有相同lifecycle時,將方法轉為數組存儲
ret[key] = ret[key].concat(mixin[key]);
} else {
ret[key] = [mixin[key]];
}
}
})
});
return ret;
};
/**
* 重復沖突處理借鑒vue:
* data, methods會合并,組件自身具有最高優先級,其次mixins中后配置的mixin優先級較高
* lifecycle不會合并。先順序執行mixins中的lifecycle,再執行組件自身的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;
};小結 1、本文主要講了如何為小程序增加mixin支持。實現思路為:預處理configObj Page(createPage(configObj)) 2、在處理mixin重復時,與vue保持一致: data, methods會合并,組件自身具有最高優先級,其次mixins中后配置的mixin優先級較高。 lifecycle不會合并。先順序執行mixins中的lifecycle,再執行組件自身的lifecycle。 以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網! 相關推薦: 以上就是微信小程序開發教程之增加mixin擴展的詳細內容,更多請關注php中文網其它相關文章! 小程序是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或者搜一下即可打開應用。 |
溫馨提示:喜歡本站的話,請收藏一下本站!