# 【方案】-基于tina的小程序埋点方案

# 前言

这里简单的介绍一个小程序的埋点方案,总体设计的思路是借鉴于Vue2中对数组的处理,而且这个方案不单单可以应用于tina,现在市场上的大多数小程序框架都可以使用这个思路

# 需求

现在需要设计一个埋点方案,让每一个页面对应一个点logType, 这个页面上的各种功能对应一个点subLogType,以及埋点所需要的数据如userId: xxxx,并且每个页面的进入、离开、销毁、返回都要自动的埋相应的点

# 注入埋点钩子函数

我们会发现tina的页面用法和组件用法不同于我们原生的小程序,我们可以在官网看到这样的用法




 















/**
  * /demo-page.js or <script> in demo-page.mina
  */
import { Page } from '@tinajs/tina'

Page.define({
  data: {
    count: 0,
  },
  onLoad () {
    console.log(this.data.count)
  },
  methods: {
    handleTapButton () {
      console.log(this.data.count)
    },
  },
})

如果说需要每一个页面都在onLoad里面调用某个方法来上报某一个logType,那实在是太麻烦了,那有没有办法可以自定义一个钩子函数logType来表示这个页面的点呢?

我们借鉴Vue中对数组方法的处理(重写数组方法),来一手狸猫换太子,就可以实现类似这样的功能了




 













import { Page } from '@tinajs/tina'

Page.define({
  logType: '10000', // 表示这个页面的点是10000
  data: {
    count: 0,
  },
  onLoad () {
    console.log(this.data.count)
  },
  methods: {
    handleTapButton () {
      console.log(this.data.count)
    },
  },
})

我们从tina的用法入手




 

import { Page } from '@tinajs/tina'

Page.define({
})

我们可以将Page的进行重写, 让他支持我们期望的效果




 























// lib/tina
import { Page } from '@tinajs/tina'

function createSetLogTypeMixin(options) {
  return {
    onLoad() {
      this.logType = options.logType
    },
  }
}

const definePage = Page.define // 将Page.define缓存起来

Page.define = function (options) {
  const setLogType = createSetLogTypeMixin({
    logType: options.logType,
  })

  options.mixins = options.mixins || []
  options.mixins.push(setLogType) // mixin注入 将logType挂载到this上
  return definePage.call(Page, options) // 修改this指向
}

module.exports = {
  Page,
}

我们通过重写Page.define方法以及mixin的机制,在页面上注入一个新的钩子函数logType,实际上就是将页面上的logType挂载到this上,实现我们想要的效果, 我们只需要在页面引用我们重写的Tina实例就好了




 

import { Page } from './../../lib/tina'
Page.define({
    logType: '10000',
})

# 统一埋点方法

有了logType了,我们还需要一个方法来发起请求上报我们的埋点,那还是用mixin吧




 











// lib/tina
const pageCommonMixin = {
    methods: {
        log(...args) {
            const logType = this.logType // 页面的点 识别哪个页面
            const subLogType = args[0] // 功能点
            const logData = args[1] // 附带的数据

            console.log('log', logType, subLogType, logData) // 模拟埋点流程
        }
    },
}

Page.mixin(pageCommon) // 添加mixin,每个页面可以通过this.log(logType, subLogType, logData)的方式上报埋点

# 实现页面动作的自动上报

每个页面的进入、离开、销毁、返回都要自动的埋相应的点,我们还是通过mixin来实现这个效果




 





























// lib.tina
function pageLog() {
  return {
    onShow() {
      console.log(1003)
      this.log(1003)
    },
    onLoad() {
      console.log(1000)
      this.log(1000)
    },
    onHide() {
      console.log(1004)
      this.log(1004)
    },
    onUnload() {
      console.log(1002)
      this.log(1002)
    },
  }
}

Page.define = function (options) {
  const setLogType = createSetLogTypeMixin({
    logType: options.logType,
  })

  options.mixins = options.mixins || []
  options.mixins.push(setLogType)
  options.mixins.push(pageLog) // 新增
  return definePage.call(Page, options)
}

我们只需要再添加一个新的mixin,在小程序的各种生命周期里面根据页面的logType进行埋点上报就好了

# 总结

这套埋点方案的核心在于重写tina.define方法,在每个页面新增埋点钩子logType,实现的思路参考Vue的源码,剩余的部分和其他的埋点方案其实没什么区别,都是通过mixin来进行全局注入一些方法等等