UNPKG

vue-auto-track

Version:

auto tracking for vue

249 lines (247 loc) 6.87 kB
import Exposure from "vue-auto-track/src/untils/exposure"; import { // PageLifeCycle, AppLifeCycle, VueLifeCycle, } from "vue-auto-track/src/untils/lifecycle"; import initNativeInfo, { thirdTrack, } from "vue-auto-track/src/untils/get-upload"; import { getUuid } from "./untils/tools.js"; import { MAX_LOCALSTORAGE, ENV_WX } from "vue-auto-track/src/untils/global"; const observesPg = []; const observesCp = []; let pageConfig = {}; let trackFn = null; let methodsUid = {}; let currentPage = null; let VueComponent = null; let pageInTime = 0; let pageOutTime = 0; let pages = []; let trigTrackTimer = null; let linkId = ""; const trackMixin = { // ...PageLifeCycle, ...AppLifeCycle, ...VueLifeCycle, data() { return {}; }, onLaunch() { linkId = getUuid(); }, onShow() { pageInTime = new Date().getTime(); pageOutTime = 0; if (this.mpType) { trackFn("page_in", {}, "page"); } if (!pageConfig[currentPage]) { return; } pageConfig[currentPage].selectorsPg.forEach((selector) => { const observe = new Exposure(this); observe.startObserver(selector.selector, (res) => { if (res.intersectionRatio === 1) { const pros = Object.keys(this); let trackData = {}; for (let pro of pros) { if (typeof this[pro] === `function`) { continue; } else { if (/^_|\$/.test(pro)) { continue; } if (~[`mpHost`, `mpType`].indexOf(pro)) { continue; } trackData[pro] = this[pro]; } } trackFn(`exposure`, trackData); } }); observesPg.push(observe); }); }, onUnload() { methodsUid = {}; while (observesCp.length) { observesCp.shift().disconnect(); } }, onHide() { methodsUid = {}; if (!this.mpType) { // 应用隐藏到后台 trackFn(`quit`, {}, "aplication"); } else { pageOutTime = new Date().getTime(); trackFn("page_out", {}, "page"); } while (observesPg.length) { observesPg.shift().disconnect(); } }, mounted() { if (this.mpType === `page`) { return; } if (!pageConfig[currentPage]) { return; } pageConfig[currentPage].selectorsCp.forEach((selector) => { const observe = new Exposure(this); observe.startObserver(selector.selector, (res) => { if (res.intersectionRatio === 1) { const pros = Object.keys(this); let trackData = {}; for (let pro of pros) { if (typeof this[pro] === `function`) { continue; } else { if (/^_|\$/.test(pro)) { continue; } if (~[`mpHost`, `mpType`].indexOf(pro)) { continue; } trackData[pro] = this[pro]; } } trackFn(`exposure`, trackData); } }); observesCp.push(observe); }); }, created() { if (this.mpType === `page`) { pages = getCurrentPages(); currentPage = this.__route__; } let trackFns = []; let trackData = {}; const pros = Object.keys(this); for (let pro of pros) { if (typeof this[pro] === `function`) { if (/^_|\$/.test(pro)) { continue; } if (trackFns.indexOf(pro) !== -1) { throw new Error(`实例中存在重名的方法--${pro}`); } if (methodsUid[pro]) { if ( methodsUid[pro] !== trackFns.sort().toString() + this.$options.name ) { console.warn( `页面结构中不同组件存在同名方法${pro},请对同名方法进行区分,否则无法进行埋点分析` ); } } else { methodsUid[pro] = trackFns.sort().toString() + this.$options.name; } trackFns.push(pro); } else { if (/^_|\$/.test(pro)) { continue; } if (~[`mpHost`, `mpType`].indexOf(pro)) { continue; } trackData[pro] = ``; } } for (let fn of trackFns) { const newFn = this[fn]; let pageEvent = []; let contentEvent = []; if (pageConfig[currentPage]) { pageEvent = pageConfig[currentPage].pageEvent || []; contentEvent = pageConfig[currentPage].contentEvent || []; } this[fn] = (arg1, arg2, arg3, arg4, arg5) => { if (arguments.length > 5) { throw new Error(`方法${fn}的入参数量不能大于5`); } if (fn.indexOf("track") !== -1) { if (!trigTrackTimer) { if (arg1 && arg2 && arg3) { trackFn(fn, { arg1, arg2, arg3 }); } else if (arg1 && arg2) { trackFn(fn, { arg1, arg2 }); } else { trackFn(fn, { arg1 }); } } else { clearTimeout(trigTrackTimer); } trigTrackTimer = setTimeout(() => { trigTrackTimer = null; }, 300); } return newFn(arg1, arg2, arg3, arg4, arg5); }; } }, }; export default { install(Vue, options) { // let init = Vue.prototype._init // // init.call(Vue) // Vue.prototype._init = function (op) { // console.log(1111,op) // init.call(this, op) // } if (!options.env || !options.upload) { throw new Error(`请配置环境以及上传埋点数据的请求`); } if (options.env == ENV_WX) { if (options.size >= MAX_LOCALSTORAGE) { throw new Error(`上传触发最大存储限制不能超过${MAX_LOCALSTORAGE}字节`); } } if (options.upload.then) { throw new Error(`请求必须配置为promise对象`); } pageConfig = options.pageConfig || {}; VueComponent = Vue; initNativeInfo(options.env); let { plugins = [] } = options; trackFn = (eventCode, data, eventType = "component") => { let page = (pages.length && pages[pages.length - 1].route) || ""; // let from_page = // (pages.length && // pages[pages.length - 1] && // pages[pages.length - 1].route) || // ""; plugins.length && options.plugins.forEach((item) => item(eventCode, { // from_page, pageInTime: pageInTime + "", pageOutTime: pageOutTime + "", pageId: page, ...data, }) ); thirdTrack( eventCode, { // from_page, eventType, pageInTime: pageInTime + "", pageOutTime: pageOutTime + "", pageId: page, linkId, ...data, }, options ); }; Vue.mixin(trackMixin); }, };