了解微信小程序 Taro 的自动埋点
相关学习推荐:小程序开发教程
在做各种各样的业务时,我们不可避免的需要在业务中进行埋点,这些埋点通常包含但不限于曝光、点击、停留时长、离开页面等场景,而在小程序中因为其和浏览器不同的架构,导致了监听页面变的更加困难,通常我们都会通过重写 Page
方法来达到对小程序原生生命周期的拦截代理,从而进行业务埋点,但是在 Taro
中这一切变得不同了。
现状
在多端统一的Taro
中,我们不再能看到显式的 Page
调用,甚至 Taro
打包之后的代码里也不再存在任何 Page
的迹象,取而代之的则是小程序原生的 Component
(这一点大家通过观察打包后的内容可以得知),所以为了实现微信小程序在Taro
中的自动埋点,我们需要换一个策略:重写Component
。
基本的重写
在微信小程序中,其暴露的Component
和 Page
能够直接被重写并进行赋值:
const _originalComponent = Component;const wrappedComponent = function (options) { ...do something before real Component return _originalComponent(options); }复制代码
这样可以很快的解决问题,但是当我们在另一个小程序做这件事情的时候,我们就又需要手动做一次这些处理,难免有些麻烦,为什么不找一个更通用的方案,我们只用关注我们需要关注的业务(埋点)就行了呢?
解决方案
重中之重,从零开始思考,掌握真正问题,接近问题本质
根问题
在解决问题之前,不如让我们先看看这个问题的本质是什么。想在小程序中进行自动的埋点,其实要做的就是在小程序指定的生命周期里做一些固定的处理,所以我们自动埋点的问题实际上是如何劫持小程序的生命周期,而要劫持小程序的生命周期,我们需要做的就是去重写options
。
如何解决
在解决这个问题之前,我们要把自己需要解决的问题拆分出来:
- 应该怎么重写
options
- 应该重写哪些
options
- 怎样把自己的业务注入到监听的生命周期中。
我们在上面的基础解决办法对如何重写options
就已经有了答案,我们只需要在原小程序提供的方法外再包裹一层即可解决,同时为了保证我们的解决方案能适用于原生小程序和Taro
这种多端统一的小程序方案,我们应该同时支持重写Component
和Page
,而对于最后一个问题,我们可以思考一下js
中的事件系统,相似的我们也可以实现一套发布订阅的逻辑,只需要定制触发事件(生命周期)和listeners
,再针对生命周期原有逻辑进行包装即可;
step 1
首先我们在重写Component
和Page
之前应当保存原始的方法,避免原始方法被污染我们无法回退,这之后再去将小程序中的所有生命周期进行枚举生成一个默认的事件对象中,保证我们在注册了对应生命周期的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<string, WeappLifecycleHook[]>); }复制代码
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 的自动埋点的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

闲鱼官方微信小程序悄然上线,在小程序中可以发布闲置与买家/卖家私信交流、查看个人资料及订单、搜索物品等,有用好奇闲鱼微信小程序叫什么,现在快来看一下。闲鱼微信小程序叫什么答案:闲鱼,闲置交易二手买卖估价回收。1、在小程序中可以发布闲置、与买家/卖家私信交流、查看个人资料及订单、搜索指定物品等功能;2、在小程序的页面中有首页、附近、发闲置、消息、我的5项功能;3、想要使用的话必要要开通微信支付才可以购买;

微信小程序实现图片上传功能随着移动互联网的发展,微信小程序已经成为了人们生活中不可或缺的一部分。微信小程序不仅提供了丰富的应用场景,还支持开发者自定义功能,其中包括图片上传功能。本文将介绍如何在微信小程序中实现图片上传功能,并提供具体的代码示例。一、前期准备工作在开始编写代码之前,我们需要先下载并安装微信开发者工具,并注册成为微信开发者。同时,还需要了解微信

实现微信小程序中的下拉菜单效果,需要具体代码示例随着移动互联网的普及,微信小程序成为了互联网开发的重要一环,越来越多的人开始关注和使用微信小程序。微信小程序的开发相比传统的APP开发更加简便快捷,但也需要掌握一定的开发技巧。在微信小程序的开发中,下拉菜单是一个常见的UI组件,实现了更好的用户操作体验。本文将详细介绍如何在微信小程序中实现下拉菜单效果,并提供具

实现微信小程序中的图片滤镜效果随着社交媒体应用的流行,人们越来越喜欢在照片中应用滤镜效果,以增强照片的艺术效果和吸引力。在微信小程序中也可以实现图片滤镜效果,为用户提供更多有趣和创造性的照片编辑功能。本文将介绍如何在微信小程序中实现图片滤镜效果,并提供具体的代码示例。首先,我们需要在微信小程序中使用canvas组件来加载和编辑图片。canvas组件可以在页面

使用微信小程序实现轮播图切换效果微信小程序是一种轻量级的应用程序,具有简单、高效的开发和使用特点。在微信小程序中,实现轮播图切换效果是常见的需求。本文将介绍如何使用微信小程序实现轮播图切换效果,并给出具体的代码示例。首先,在微信小程序的页面文件中,添加一个轮播图组件。例如,可以使用<swiper>标签来实现轮播图的切换效果。在该组件中,可以通过b

实现微信小程序中的图片旋转效果,需要具体代码示例微信小程序是一种轻量级的应用程序,为用户提供了丰富的功能和良好的用户体验。在小程序中,开发者可以利用各种组件和API来实现各种效果。其中,图片旋转效果是一种常见的动画效果,可以为小程序增添趣味性和视觉效果。在微信小程序中实现图片旋转效果,需要使用小程序提供的动画API。下面是一个具体的代码示例,展示了如何在小程

实现微信小程序中的滑动删除功能,需要具体代码示例随着微信小程序的流行,开发者们在开发过程中经常会遇到一些常见功能的实现问题。其中,滑动删除功能是一个常见、常用的功能需求。本文将为大家详细介绍如何在微信小程序中实现滑动删除功能,并给出具体的代码示例。一、需求分析在微信小程序中,滑动删除功能的实现涉及到以下要点:列表展示:要显示可滑动删除的列表,每个列表项需要包

闲鱼官方微信小程序已经悄然上线,它为用户提供了一个便捷的平台,让你可以轻松地发布和交易闲置物品。在小程序中,你可以与买家或卖家进行私信交流,查看个人资料和订单,以及搜索你想要的物品。那么闲鱼在微信小程序中究竟叫什么呢,这篇教程攻略将为您详细介绍,想要了解的用户们快来跟着本文继续阅读吧!闲鱼微信小程序叫什么答案:闲鱼,闲置交易二手买卖估价回收。1、在小程序中可以发布闲置、与买家/卖家私信交流、查看个人资料及订单、搜索指定物品等功能;2、在小程序的页面中有首页、附近、发闲置、消息、我的5项功能;3、
