热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

了解微信小程序Taro的自动埋点

本文是了解微信小程序Taro的自动埋点。

相关学习推荐:小程序开发教程

在做各种各样的业务时,我们不可避免的需要在业务中进行埋点,这些埋点通常包含但不限于曝光、点击、停留时长、离开页面等场景,而在小程序中因为其和浏览器不同的架构,导致了监听页面变的更加困难,通常我们都会通过重写 Page 方法来达到对小程序原生生命周期的拦截代理,从而进行业务埋点,但是在 Taro 中这一切变得不同了。

现状

在多端统一的Taro中,我们不再能看到显式的 Page 调用,甚至 Taro 打包之后的代码里也不再存在任何 Page 的迹象,取而代之的则是小程序原生的 Component(这一点大家通过观察打包后的内容可以得知),所以为了实现微信小程序在Taro中的自动埋点,我们需要换一个策略:重写Component

基本的重写

在微信小程序中,其暴露的ComponentPage 能够直接被重写并进行赋值:

const _originalCompOnent= Component;const wrappedCompOnent= function (options) {
    ...do something before real Component    return _originalComponent(options);
}

这样可以很快的解决问题,但是当我们在另一个小程序做这件事情的时候,我们就又需要手动做一次这些处理,难免有些麻烦,为什么不找一个更通用的方案,我们只用关注我们需要关注的业务(埋点)就行了呢?

解决方案

重中之重,从零开始思考,掌握真正问题,接近问题本质

根问题

在解决问题之前,不如让我们先看看这个问题的本质是什么。想在小程序中进行自动的埋点,其实要做的就是在小程序指定的生命周期里做一些固定的处理,所以我们自动埋点的问题实际上是如何劫持小程序的生命周期,而要劫持小程序的生命周期,我们需要做的就是去重写options

如何解决

在解决这个问题之前,我们要把自己需要解决的问题拆分出来:

  • 应该怎么重写 options
  • 应该重写哪些 options
  • 怎样把自己的业务注入到监听的生命周期中。

我们在上面的基础解决办法对如何重写options就已经有了答案,我们只需要在原小程序提供的方法外再包裹一层即可解决,同时为了保证我们的解决方案能适用于原生小程序和Taro这种多端统一的小程序方案,我们应该同时支持重写ComponentPage,而对于最后一个问题,我们可以思考一下js中的事件系统,相似的我们也可以实现一套发布订阅的逻辑,只需要定制触发事件(生命周期)和listeners,再针对生命周期原有逻辑进行包装即可;

step 1

首先我们在重写ComponentPage之前应当保存原始的方法,避免原始方法被污染我们无法回退,这之后再去将小程序中的所有生命周期进行枚举生成一个默认的事件对象中,保证我们在注册了对应生命周期的listeners后能通过寻址找到并对原生命周期方法进行重写。

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();
}// 初始化所有生命周期的钩子函数private initLifecycleHooks(): void {  this.lifecycleHooks = Object.keys(ProxyLifecycle).reduce((res, cur: keyof typeof ProxyLifecycle) => {
    res[ProxyLifecycle[cur]] = [] as WeappLifecycleHook[];    return res;
  }, {} as Record);
}

step 2

在这一步我们只需要将监听函数放到我们第一步中声明的事件对象中,然后执行重写流程即可:

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;
}/**
 * 为对应的生命周期重写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 为生命周期添加的钩子函数
 * @param optionsKey 需要被重写的optionsKey,仅用于 lifetime 模式
 * @param options 需要被重写的配置项
 * @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;
};

经过如上两步,我们就能对指定的生命周期进行劫持并注入我们自己的listeners,使用被重写过Component或者Page就会自动触发这些 listeners

weapp-lifecycle-hook-plugin

为了方便直接对微信小程序原生环境和Taro等多端统一方案进行这一套通用的解决方案,我实现了一个插件来解决这个问题(私心安利)

安装

npm install weapp-lifecycle-hook-plugin
或者
yarn add weapp-lifecycle-hook-plugin

使用

import OverrideWechatPage, { setupLifecycleListeners, ProxyLifecycle } from 'weapp-lifecycle-hook-plugin';

// 供 setupLifecycleListeners 使用的 hook 函数,接受一个参数,为当前组件/页面的options
function simpleReportGoPage(options: any): void {
  console.log('goPage', options);
}

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

  componentWillMount() {
    // ...
    // 手动创建的实例和使用 setupLifecycleListeners 创建的实例不是同一个,所以需要销毁时需要单独对其进行销毁
    // 直接调用实例方式
    const instance = new OverrideWechatPage(this.config.pages);
    // 直接调用实例上的 addListener 方法在全局增加监听函数,可链式调用
    instance.addLifecycleListener(ProxyLifecycle.SHOW, simpleReportGoPage);
    // setupListeners 的使用
    setupLifecycleListeners(ProxyLifecycle.SHOW, [simpleReportGoPage], this.config.pages);
    // ...
  }

  // ...
}

只需要通过简单地 setup 就能解决以前需要手动书写一大堆的重写逻辑,何乐而不为呢

想了解更多编程学习,敬请关注php培训栏目!

以上就是了解微信小程序 Taro 的自动埋点的详细内容,更多请关注其它相关文章!


推荐阅读
  • 手把手教你使用GraphPad Prism和Excel绘制回归分析结果的森林图
    本文介绍了使用GraphPad Prism和Excel绘制回归分析结果的森林图的方法。通过展示森林图,可以更加直观地将回归分析结果可视化。GraphPad Prism是一款专门为医学专业人士设计的绘图软件,同时也兼顾统计分析的功能,操作便捷,可以帮助科研人员轻松绘制出高质量的专业图形。文章以一篇发表在JACC杂志上的研究为例,利用其中的多因素回归分析结果来绘制森林图。通过本文的指导,读者可以学会如何使用GraphPad Prism和Excel绘制回归分析结果的森林图。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 微信民众号商城/小顺序商城开源项目介绍及使用教程
    本文介绍了一个基于WeiPHP5.0开发的微信民众号商城/小顺序商城的开源项目,包括前端和后端的目录结构,以及所使用的技术栈。同时提供了项目的运行和打包方法,并分享了一些调试和开发经验。最后还附上了在线预览和GitHub商城源码的链接,以及加入前端交流QQ群的方式。 ... [详细]
  • 校园表白墙微信小程序,校园小情书、告白墙、论坛,大学表白墙搭建教程
    小程序的名字必须和你微信注册的名称一模一样在后台注册好小程序。mp.wx-union.cn后台域名https。mp.wx-union.cn ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
  • 微信答题小程序的设计与实现详解
    本文详细介绍了如何设计和实现一个微信答题小程序,包括题库的设计和题目的呈现。通过抽取题目编号和使用全局变量记录当前题目的信息,实现了题目的刷新和显示。同时,还介绍了题目的展示方式和容器的创建。本文适合零基础的小白学习微信答题小程序的开发。 ... [详细]
  • PHP小习题:PHP小练习题前几天在百度知道里面看到有位网友询问如何制作一下的小程序:用php语言设计一个小程序,计算今天到达下月的天数、全部输出这些天数,并使得每天的日期以三种颜 ... [详细]
  • vuecli创建项目(详情步骤)
    1、安装node环境2、下载vue和vue-cli脚手架命令行输入npm ... [详细]
  • 项目需要实现弹幕,网上参考了各种方法,最后觉得transform+transition实现的效果在移动设备上性能最好,在iphone6和红米4上测试,看不到 ... [详细]
  • 问题描述:域名已经备案,我全部都有,也在后台配置了,但是手机预览,还是请求失败,PC端是可以请求 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 企业数据应用挑战及元数据管理的重要性
    本文主要介绍了企业在日常经营管理过程中面临的数据应用挑战,包括数据找不到、数据读不懂、数据不可信等问题。针对这些挑战,通过元数据管理可以实现数据的可见、可懂、可用,帮助业务快速获取所需数据。文章提出了“灵魂”三问——元数据是什么、有什么用、又该怎么管,强调了元数据管理在企业数据治理中的基础和前提作用。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 微信开放外链的第二阶段:腾讯和阿里巴巴的博弈
    2021年11月30日,微信开始进行“开放外链”的第二阶段,允许在微信个人会话中打开外部链接和在微信群中打开电商链接。虽然这是腾讯和阿里巴巴都能接受的阶段性结果,但双方都不会太满意。接下来几个月,腾讯和阿里将展开复杂的博弈,我们作为外人很难看清全过程。工信部从未要求腾讯无条件开放微信API,本次开放的也只是普通的HTTP链接。 ... [详细]
author-avatar
世界第一1945_307
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有