欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

微信小程序的自動埋點(diǎn) - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏壧峁┍憬莸闹С郑?

您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

微信小程序的自動埋點(diǎn)

發(fā)表時間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):70

在做各種各樣的業(yè)務(wù)時,我們不可避免的需要在業(yè)務(wù)中進(jìn)行埋點(diǎn),這些埋點(diǎn)通常包含但不限于曝光、點(diǎn)擊、停留時長、離開頁面等場景,而在小程序中因?yàn)槠浜蜑g覽器不同的架構(gòu),導(dǎo)致了監(jiān)聽頁面變的更加困難,通常我們都會通過重寫 Page 方法來達(dá)到對小程序原生生命周期的攔截代理,從而進(jìn)行業(yè)務(wù)埋點(diǎn),但是在 Taro 中這一切變得不同了。

現(xiàn)狀

在多端統(tǒng)一的 Taro 中,我們不再能看到顯式的 Page 調(diào)用,甚至 Taro 打包之后的代碼里也不再存在任何 Page 的跡象,取而代之的則是小程序原生的 Component (這一點(diǎn)大家通過觀察打包后的內(nèi)容可以得知),所以為了實(shí)現(xiàn)微信小程序在 Taro 中的自動埋點(diǎn),我們需要換一個策略:重寫 Component 。

基本的重寫

在微信小程序中,其暴露的 ComponentPage 能夠直接被重寫并進(jìn)行賦值:

const _originalComponent = Component;

const wrappedComponent = function (options) {
    ...do something before real Component
    return _originalComponent(options);
}
復(fù)制代碼

這樣可以很快的解決問題,但是當(dāng)我們在另一個小程序做這件事情的時候,我們就又需要手動做一次這些處理,難免有些麻煩,為什么不找一個更通用的方案,我們只用關(guān)注我們需要關(guān)注的業(yè)務(wù)(埋點(diǎn))就行了呢?

解決方案

重中之重,從零開始思考,掌握真正問題,接近問題本質(zhì)

根問題

在解決問題之前,不如讓我們先看看這個問題的本質(zhì)是什么。想在小程序中進(jìn)行自動的埋點(diǎn),其實(shí)要做的就是在小程序指定的生命周期里做一些固定的處理,所以我們自動埋點(diǎn)的問題實(shí)際上是如何劫持小程序的生命周期,而要劫持小程序的生命周期,我們需要做的就是去重寫 options 。

如何解決

在解決這個問題之前,我們要把自己需要解決的問題拆分出來:

options
options

我們在上面的基礎(chǔ)解決辦法對如何重寫 options 就已經(jīng)有了答案,我們只需要在原小程序提供的方法外再包裹一層即可解決,同時為了保證我們的解決方案能適用于原生小程序和 Taro 這種多端統(tǒng)一的小程序方案,我們應(yīng)該同時支持重寫 ComponentPage ,而對于最后一個問題,我們可以思考一下 js 中的事件系統(tǒng),相似的我們也可以實(shí)現(xiàn)一套發(fā)布訂閱的邏輯,只需要定制觸發(fā)事件(生命周期)和 listeners ,再針對生命周期原有邏輯進(jìn)行包裝即可;

step 1

首先我們在重寫 ComponentPage 之前應(yīng)當(dāng)保存原始的方法,避免原始方法被污染我們無法回退,這之后再去將小程序中的所有生命周期進(jìn)行枚舉生成一個默認(rèn)的事件對象中,保證我們在注冊了對應(yīng)生命周期的 listeners 后能通過尋址找到并對原生命周期方法進(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);
}
復(fù)制代碼

step 2

在這一步我們只需要將監(jiān)聽函數(shù)放到我們第一步中聲明的事件對象中,然后執(zhí)行重寫流程即可:

public addLifecycleListener(lifeTimeOrLifecycle: string, listener: WeappLifecycleHook): OverrideWechatPage {
  // 針對指定周期定義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;
}

/**
 * 為對應(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)過如上兩步,我們就能對指定的生命周期進(jìn)行劫持并注入我們自己的 listeners ,使用被重寫過 Component 或者 Page 就會自動觸發(fā)這些 listeners

weapp-lifecycle-hook-plugin

為了方便直接對微信小程序原生環(huán)境和 Taro 等多端統(tǒng)一方案進(jìn)行這一套通用的解決方案,我實(shí)現(xiàn)了一個插件來解決這個問題(私心安利)

安裝

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ù),接受一個參數(shù),為當(dāng)前組件/頁面的options
function simpleReportGoPage(options: any): void {
  console.log('goPage', options);
}

// setupListeners
class App extends Component {
  constructor(props) {
    super(props);
  }

  componentWillMount() {
    // ...
    // 手動創(chuàng)建的實(shí)例和使用 setupLifecycleListeners 創(chuàng)建的實(shí)例不是同一個,所以需要銷毀時需要單獨(dú)對其進(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ù)制代碼

只需要通過簡單地 setup 就能解決以前需要手動書寫一大堆的重寫邏輯,何樂而不為呢 :stuck_out_tongue_closed_eyes:

相關(guān)案例查看更多