知識(shí)
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!
您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >
使用MpKit的事件、Mixin、SetData優(yōu)化、全局?jǐn)r截等功能增強(qiáng)開發(fā)多平臺(tái)小程序 ...
發(fā)表時(shí)間:2021-1-11
發(fā)布人:葵宇科技
瀏覽次數(shù):74
前言
近年來,多個(gè)公司都開發(fā)出了小程序這樣的“微應(yīng)用”方案,其在生態(tài)擴(kuò)展、功能增強(qiáng)等方面都發(fā)揮著重要的作用;
作為開發(fā)者卻要同時(shí)面對(duì)多個(gè)小程序平臺(tái),實(shí)現(xiàn)相似的功能,如果不考慮使用框架的話,在底層的一些基礎(chǔ)技術(shù)解決方案上,有沒有一個(gè)輕量級(jí)的選擇?
我們?cè)陂_發(fā)一個(gè)小程序時(shí),往往會(huì)有以下技術(shù)需求:
- 全局事件總線
- 優(yōu)化小程序的setData函數(shù)
- 希望將App/Page/Component上的共有功能拆分,并可以有效性的重復(fù)利用,甚至組建為App/Page/Component基類
- 可以全局?jǐn)r截執(zhí)行某些操作,如:異常報(bào)錯(cuò)、網(wǎng)絡(luò)請(qǐng)求、功能制止、App/Page/Component的生命周期等
基于以上需求,都是我以往實(shí)現(xiàn)過的功能,所以我將我的經(jīng)驗(yàn)總結(jié)成了一個(gè)開源項(xiàng)目MpKit,里面就包含對(duì)以上需求的功能實(shí)現(xiàn),且不止于此;
MpKit的主要功能都經(jīng)過單元測試,可放心使用
下面我來介紹下它的具體用法和功能列表。
簡介
MpKit發(fā)布到了NPM平臺(tái),以模塊化的方式劃分為多個(gè)包,某些包不止能用在小程序平臺(tái),還可以用到h5等平臺(tái);某些包卻無法在小程序上使用,包列表及相關(guān)功能如下:
以下包均支持TypeScript語言
安裝
如果你的小程序項(xiàng)目中支持引入npm包,那么你直接根據(jù)自己的需要安裝對(duì)應(yīng)包即可,如:
npm i @mpkit/ebus -S
但是如果你是原生開發(fā),不支持引入npm包,你最大的可能需要用到 @mpkit/inject
包,此包中的功能基本包含了其他包的所有功能,且支持按需插件化安裝,可節(jié)省你的字節(jié)空間;使用 @mpkit/inject
:
xx/temp
npm i @mpkit/inject
-
找到
xx/temp/node_modules/@mpkit/inject
下的dist
目錄,將其下內(nèi)容拷貝到你的小程序項(xiàng)目目錄下; -
找到
dist/config.js
文件,將你需要的功能插件引入,如:
// 提供事件類功能
import { plugin as EbusPlugin } from './plugins/ebus';
// 提供混入功能
import { plugin as MixinPlugin } from './plugins/mixin';
// 提供setData優(yōu)化
import { plugin as SetDataPlugin } from './plugins/set-data';
var config = {
// 是否重寫全局變量
rewrite: {
App: false, // 重寫全局變量App為 plugins/mixin 中的MkApp 即 MpKit.App
Page: false, // 重寫全局變量Page為 plugins/mixin 中的MkPage 即 MpKit.Page
Component: false, // 重寫全局變量Component為 plugins/mixin 中的MkComponent 即 MpKit.Component
Api: false, // 重寫全局api變量wx/my/tt為 plugins/mixin 中的MkApi 即 MpKit.Api
setData: false // 重寫Page/Component中的setData為優(yōu)化后的setData 即 MpKit.setData
},
plugins: [
EbusPlugin,
MixinPlugin,
SetDataPlugin
]
};
export default config;
-
如果配置了
config.rewrite
項(xiàng),請(qǐng)?jiān)谛〕绦蝽?xiàng)目的app.js
的第一行處引入@mpkit/inject/dist
中的index.js
文件,否則無法實(shí)現(xiàn)全局變量重寫;如果沒有配置該項(xiàng),則需要在使用時(shí)引入,如:
import MpKit from '@mpkit/inject/dist/index';
MpKit.on(...);
- 安裝完成。
- 小提示:不需要的插件js文件可以直接刪掉,插件不直接相互依賴。
使用
這里著重介紹 @mpkit/inject
包的使用方式和細(xì)節(jié),其他包可自行參考對(duì)應(yīng)文檔;
@mpkit/inject
包提供下列功能,
從上面的功能列表中可以看到,某些方法或變量是依賴插件的,如果沒有安裝相關(guān)插件,則無法使用對(duì)用方法;
App/Page/Component
當(dāng)使用 MpKit.App/Page/Component
時(shí),可傳遞多個(gè)對(duì)象,如:
import MpKit from '@mpkit/inject/dist/index';
// 如果在config中配置了rewrite.App=true,則調(diào)用App等同于調(diào)用了[未重寫的App(MpKit.App)]
App(MpKit.App({
globalData: {
name: 'Tom',
age: 10
},
onShow() {
console.log('onShow1')
},
add(a, b) {
return a + b;
}
}, {
globalData: {
age: 20
},
onShow() {
console.log(`onShow2, ${this.add(2, 4)}`);
console.log(this.globalData);
}
}));
// 輸出:onShow1
// 輸出:onShow2, 6
// 輸出:{ name: 'Tom', age: 20 }
Component(MpKit.Component({
data: {
name: 'Alice',
products: [
{
name: '蘋果',
price: 6
},
{
name: '香蕉',
price: 5
}
]
},
created() {
console.log('created1')
},
methods: {
sayhi() {
console.log(`hi ${this.data.name}`);
}
}
}, {
data: {
products: [
{
price: 8
}
]
},
created() {
console.log('created2');
this.sayhi();
console.log(this.data.list);
},
methods: {
sayhi() {
console.log(`你好 ${this.data.name}`);
}
}
}));
// 輸出:created1
// 輸出:created2
// 輸出:hi Alice
// 輸出:你好 Alice
// 輸出:[ { name: '蘋果', price: 8 }, { name: '香蕉', price: 5 } ]
合并策略
從上面的例子可以看出合并策略是:
- 屬性進(jìn)行深度合并
- 方法會(huì)保留所有mixin中的方法體,按照順序全部執(zhí)行
鉤子函數(shù)
為可以進(jìn)行全局?jǐn)r截 App/Page/Component/Api
上的方法,MpKit做了鉤子函數(shù)的機(jī)制,具體為:
-
每個(gè)方法執(zhí)行前會(huì)調(diào)用
before
鉤子 -
如果
before
鉤子函數(shù)存在,且有返回值(如果有多個(gè)before
鉤子則取最后一個(gè)不為undefined|true
的結(jié)果)時(shí)-
對(duì)于
App/Page/Component
如果返回值為false
,則不會(huì)繼續(xù)向下執(zhí)行 -
對(duì)于
Api
如果返回值為false
,則不會(huì)繼續(xù)向下執(zhí)行;同時(shí)如果返回值不為true
和undefined
時(shí),會(huì)直接將結(jié)果返回出去,且不會(huì)繼續(xù)向下執(zhí)行
-
對(duì)于
-
然后執(zhí)行
方法體
,如果有多個(gè),則依次全部執(zhí)行,并返回最后一個(gè)不為空的結(jié)果 -
執(zhí)行
after
鉤子,并傳入方法體
的執(zhí)行結(jié)果 -
如果是
Api
上的異步方法,還會(huì)根據(jù)結(jié)果回調(diào)(success|fail)在執(zhí)行complete
鉤子
MpKit內(nèi)置了很多鉤子,用于全局事件觸發(fā)、方法重寫等,同時(shí)你可以添加自己的鉤子函數(shù),調(diào)用:
MpKit.MixinStore.addHook(type:MpViewType.App|MpViewType.Page|MpViewType.Component|'Api', hook:MpMethodHook)
可為 App/Page/Component/Api 添加全局鉤子函數(shù); MpMethodHook
的定義如下:
interface MpMethodHookLike {
before?(
methodName: string,
methodArgs: any[],
methodHandler: Function,
funId?: string
);
after?(
methodName: string,
methodArgs: any[],
methodResult: any,
funId?: string
);
catch?(
methodName: string,
methodArgs: any[],
error: Error,
errType?: string,
funId?: string
);
complete?(
methodName: string,
methodArgs: any[],
res: any,
success?: boolean,
funId?: string
);
}
interface MpMethodHook extends MpMethodHookLike {
[prop: string]: Function | MpMethodHookLike;
}
示例1:
import MpKit from "@mpkit/inject/dist/index";
import { MpViewType } from "@mpkit/inject/dist/types";
MpKit.MixinStore.addHook(MpViewType.App, {
before(methodName, methodArgs) {
console.log(`before methodName=${methodName}`);
},
after(methodName, methodArgs, methodResult) {
console.log(`after methodName=${methodName}, ${methodResult}`);
},
catch(methodName, methodArgs, error) {
console.log(`catch err=${error.message}`);
},
});
App(
MpKit.App({
onLaunch() {
this.add(1, 2);
},
onShow() {
throw new Error("test");
},
add(a, b) {
return a + b;
},
})
);
// 輸出:before methodName=onLaunch
// 輸出:before methodName=add
// 輸出:after methodName=add, 2
// 輸出:after methodName=onLaunch,
// 輸出:before methodName=onShow,
// 輸出:catch err=test
MpKit.MixinStore.addHook("Api", {
before(methodName, methodArgs, methodHandler, funId) {
console.log(`before api=${methodName}`);
},
after(methodName, methodArgs, methodResult, funId) {
console.log(`after api=${methodName}, ${methodResult}`);
},
complete(methodName, methodArgs, res, isSuccess, funId) {
console.log(`complete api=${methodName}, ${isSuccess}, ${res}`);
},
});
MpKit.Api.request({
url: "...",
});
// 輸出:before api=request
// 輸出:after api=request, [RequestTask Object]
// 假設(shè)請(qǐng)求成功且返回字符串“1”,則輸出:complete api=request, true, 1
// 假設(shè)請(qǐng)求失敗,則輸出:complete api=request, false, { errMsg:'...' }
示例2:當(dāng)在 before
鉤子中返回 false
會(huì)具體值時(shí):
MpKit.MixinStore.addHook(MpViewType.App, {
onShow: {
before(methodName, methodArgs) {
console.log("hook onShow");
return false;
},
},
});
App(
MpKit.App({
onLaunch() {},
onShow() {
console.log("self onShow");
},
})
);
// 僅輸出:hook onShow
const store = {};
MpKit.MixinStore.addHook("Api", {
before(methodName, methodArgs, methodHandler, funId) {
console.log(`before methodName=${methodName}`);
if (methodName === "setStorageSync") {
store[methodArgs[0]] = methodArgs[1];
}
if (methodName === "getStorageSync") {
// 并不會(huì)真正執(zhí)行(wx|my|tt|..).getStorageSync
return store[methodArgs[0]];
}
},
after(methodName) {
console.log(`after methodName=${methodName}`);
},
});
MpKit.Api.setStorageSync("name", "Tom");
const name = MpKit.Api.getStorageSync("name");
console.log(name === store.name);
// 輸出:before methodName=setStorageSync
// 輸出:after methodName=setStorageSync
// 輸出:before methodName=getStorageSync
// 輸出:true
結(jié)語
希望MpKit可以為你帶來便捷愉快的開發(fā)體驗(yàn),祝大家工作順心,家庭美滿,加油!
相關(guān)案例查看更多
相關(guān)閱讀
- 小程序商城
- web
- 汽車報(bào)廢回收
- 汽車報(bào)廢
- 云南小程序開發(fā)報(bào)價(jià)
- 旅游網(wǎng)站建設(shè)
- 網(wǎng)站建設(shè)需要多少錢
- 網(wǎng)站建設(shè)專家
- 昆明軟件公司
- 小程序
- 軟件定制
- 網(wǎng)站建設(shè)特性
- 云南百度小程序
- 昆明做網(wǎng)站
- 報(bào)廢車拆解回收管理系統(tǒng)
- 百度自然排名
- 智慧農(nóng)貿(mào)市場
- 迪慶小程序開發(fā)
- 貴州小程序開發(fā)
- 小程序開發(fā)課程
- web服務(wù)
- 云南網(wǎng)站開發(fā)哪家好
- 云南網(wǎng)站建設(shè)百度
- 開發(fā)框架
- 昆明網(wǎng)站建設(shè)公司
- 商標(biāo)
- 云南小程序開發(fā)首選品牌
- 網(wǎng)站優(yōu)化哪家好
- 網(wǎng)站建設(shè)方法
- 政府網(wǎng)站建設(shè)服務(wù)