您好,登錄后才能下訂單哦!
這篇文章主要介紹了微信小程序Taro的自動(dòng)埋點(diǎn)是什么,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
在多端統(tǒng)一的Taro
中,我們不再能看到顯式的 Page
調(diào)用,甚至 Taro
打包之后的代碼里也不再存在任何 Page
的跡象,取而代之的則是小程序原生的 Component
(這一點(diǎn)大家通過觀察打包后的內(nèi)容可以得知),所以為了實(shí)現(xiàn)微信小程序在Taro
中的自動(dòng)埋點(diǎn),我們需要換一個(gè)策略:重寫Component
。
在微信小程序中,其暴露的Component
和 Page
能夠直接被重寫并進(jìn)行賦值:
const _originalComponent = Component;const wrappedComponent = function (options) { ...do something before real Component return _originalComponent(options); }復(fù)制代碼
這樣可以很快的解決問題,但是當(dāng)我們?cè)诹硪粋€(gè)小程序做這件事情的時(shí)候,我們就又需要手動(dòng)做一次這些處理,難免有些麻煩,為什么不找一個(gè)更通用的方案,我們只用關(guān)注我們需要關(guān)注的業(yè)務(wù)(埋點(diǎn))就行了呢?
重中之重,從零開始思考,掌握真正問題,接近問題本質(zhì)
在解決問題之前,不如讓我們先看看這個(gè)問題的本質(zhì)是什么。想在小程序中進(jìn)行自動(dòng)的埋點(diǎn),其實(shí)要做的就是在小程序指定的生命周期里做一些固定的處理,所以我們自動(dòng)埋點(diǎn)的問題實(shí)際上是如何劫持小程序的生命周期,而要劫持小程序的生命周期,我們需要做的就是去重寫options
。
在解決這個(gè)問題之前,我們要把自己需要解決的問題拆分出來:
應(yīng)該怎么重寫 options
應(yīng)該重寫哪些 options
怎樣把自己的業(yè)務(wù)注入到監(jiān)聽的生命周期中。
我們?cè)谏厦娴幕A(chǔ)解決辦法對(duì)如何重寫options
就已經(jīng)有了答案,我們只需要在原小程序提供的方法外再包裹一層即可解決,同時(shí)為了保證我們的解決方案能適用于原生小程序和Taro
這種多端統(tǒng)一的小程序方案,我們應(yīng)該同時(shí)支持重寫Component
和Page
,而對(duì)于最后一個(gè)問題,我們可以思考一下js
中的事件系統(tǒng),相似的我們也可以實(shí)現(xiàn)一套發(fā)布訂閱的邏輯,只需要定制觸發(fā)事件(生命周期)和listeners
,再針對(duì)生命周期原有邏輯進(jìn)行包裝即可;
首先我們?cè)谥貙?code>Component和Page
之前應(yīng)當(dāng)保存原始的方法,避免原始方法被污染我們無法回退,這之后再去將小程序中的所有生命周期進(jìn)行枚舉生成一個(gè)默認(rèn)的事件對(duì)象中,保證我們?cè)谧?cè)了對(duì)應(yīng)生命周期的listeners
后能通過尋址找到并對(duì)原生命周期方法進(jìn)行重寫。
export const ProxyLifecycle = { ON_READY: 'onReady', ON_SHOW: 'onShow', ON_HIDE: 'onHide', ON_LOAD: 'onLoad', ON_UNLOAD: 'onUnload', CREATED: 'created', ATTACHED: 'attached', READY: 'ready', MOVED: 'moved', DETACHED: 'detached', SHOW: 'show', HIDE: 'hide', RESIZE: 'resize', };public constructor() { this.initLifecycleHooks(); this.wechatOriginalPage = getWxPage(); this.wechatOriginalComponent = getWxComponent(); }// 初始化所有生命周期的鉤子函數(shù)private initLifecycleHooks(): void { this.lifecycleHooks = Object.keys(ProxyLifecycle).reduce((res, cur: keyof typeof ProxyLifecycle) => { res[ProxyLifecycle[cur]] = [] as WeappLifecycleHook[]; return res; }, {} as Record<string, WeappLifecycleHook[]>); }復(fù)制代碼
在這一步我們只需要將監(jiān)聽函數(shù)放到我們第一步中聲明的事件對(duì)象中,然后執(zhí)行重寫流程即可:
public addLifecycleListener(lifeTimeOrLifecycle: string, listener: WeappLifecycleHook): OverrideWechatPage { // 針對(duì)指定周期定義Hooks this.lifecycleHooks[lifeTimeOrLifecycle].push(listener); const _Page = this.wechatOriginalPage; const _Component = this.wechatOriginalComponent; const self = this; const wrapMode = this.checkMode(lifeTimeOrLifecycle); const componentNeedWrap = ['component', 'pageLifetimes'].includes(wrapMode); const wrapper = function wrapFunc(options: IOverrideWechatPageInitOptions): string | void { const optionsKey = wrapMode === 'pageLifetimes' ? 'pageLifetimes' : ''; options = self.findHooksAndWrap(lifeTimeOrLifecycle, optionsKey, options); const res = componentNeedWrap ? _Component(options) : _Page(options); options.__router__ = (wrapper as any).__route__ = res; return res; }; (wrapper as any).__route__ = ''; if (componentNeedWrap) { overrideWxComponent(wrapper); } else { overrideWxPage(wrapper); } return this; }/** * 為對(duì)應(yīng)的生命周期重寫options * @param proxyLifecycleOrTime 需要攔截的生命周期 * @param optionsKey 需要重寫的 optionsKey,此處用于 lifetime 模式 * @param options 需要被重寫的 options * @returns {IOverrideWechatPageInitOptions} 被重寫的options */private findHooksAndWrap = ( proxyLifecycleOrTime: string, optionsKey = '', options: IOverrideWechatPageInitOptions, ): IOverrideWechatPageInitOptions => { let processedOptions = { ...options }; const hooks = this.lifecycleHooks[proxyLifecycleOrTime]; processedOptions = OverrideWechatPage.wrapLifecycleOptions(proxyLifecycleOrTime, hooks, optionsKey, options); return processedOptions; };/** * 重寫options * @param lifecycle 需要被重寫的生命周期 * @param hooks 為生命周期添加的鉤子函數(shù) * @param optionsKey 需要被重寫的optionsKey,僅用于 lifetime 模式 * @param options 需要被重寫的配置項(xiàng) * @returns {IOverrideWechatPageInitOptions} 被重寫的options */private static wrapLifecycleOptions = ( lifecycle: string, hooks: WeappLifecycleHook[], optionsKey = '', options: IOverrideWechatPageInitOptions, ): IOverrideWechatPageInitOptions => { let currentOptions = { ...options }; const originalMethod = optionsKey ? (currentOptions[optionsKey] || {})[lifecycle] : currentOptions[lifecycle]; const runLifecycleHooks = (): void => { hooks.forEach((hook) => { if (currentOptions.__isPage__) { hook(currentOptions); } }); }; const warpMethod = runFunctionWithAop([runLifecycleHooks], originalMethod); currentOptions = optionsKey ? { ...currentOptions, [optionsKey]: { ...options[optionsKey], ...(currentOptions[optionsKey] || {}), [lifecycle]: warpMethod, }, } : { ...currentOptions, [lifecycle]: warpMethod, }; return currentOptions; };復(fù)制代碼
經(jīng)過如上兩步,我們就能對(duì)指定的生命周期進(jìn)行劫持并注入我們自己的listeners
,使用被重寫過Component
或者Page
就會(huì)自動(dòng)觸發(fā)這些 listeners
。
為了方便直接對(duì)微信小程序原生環(huán)境和Taro
等多端統(tǒng)一方案進(jìn)行這一套通用的解決方案,我實(shí)現(xiàn)了一個(gè)插件來解決這個(gè)問題(私心安利)
npm install weapp-lifecycle-hook-plugin 或者 yarn add weapp-lifecycle-hook-plugin復(fù)制代碼
import OverrideWechatPage, { setupLifecycleListeners, ProxyLifecycle } from 'weapp-lifecycle-hook-plugin'; // 供 setupLifecycleListeners 使用的 hook 函數(shù),接受一個(gè)參數(shù),為當(dāng)前組件/頁面的options function simpleReportGoPage(options: any): void { console.log('goPage', options); } // setupListeners class App extends Component { constructor(props) { super(props); } componentWillMount() { // ... // 手動(dòng)創(chuàng)建的實(shí)例和使用 setupLifecycleListeners 創(chuàng)建的實(shí)例不是同一個(gè),所以需要銷毀時(shí)需要單獨(dú)對(duì)其進(jìn)行銷毀 // 直接調(diào)用實(shí)例方式 const instance = new OverrideWechatPage(this.config.pages); // 直接調(diào)用實(shí)例上的 addListener 方法在全局增加監(jiān)聽函數(shù),可鏈?zhǔn)秸{(diào)用 instance.addLifecycleListener(ProxyLifecycle.SHOW, simpleReportGoPage); // setupListeners 的使用 setupLifecycleListeners(ProxyLifecycle.SHOW, [simpleReportGoPage], this.config.pages); // ... } // ... }復(fù)制代碼
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“微信小程序Taro的自動(dòng)埋點(diǎn)是什么”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。