@tmsfe/tms-core 0.0.100 → 0.0.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmsfe/tms-core",
3
- "version": "0.0.100",
3
+ "version": "0.0.102",
4
4
  "description": "tms运行时框架",
5
5
  "repository": {
6
6
  "type": "git",
@@ -86,32 +86,6 @@ function deepClone(obj: any, depth = 0, maxDepth = 2): any {
86
86
  return newObj;
87
87
  }
88
88
 
89
- /**
90
- * 获取触发绑定事件的携带数据
91
- * @param event
92
- */
93
- function getEventExtra(event: any): any {
94
- if (!event) {
95
- return '';
96
- }
97
- const { currentTarget, mark, detail } = event;
98
- const obj = {};
99
- // 一般把数据放在dataset或者mark中
100
- const dataset = currentTarget?.dataset;
101
- if (dataset && Object.keys(dataset).length) {
102
- Object.assign(obj, { dataset });
103
- }
104
- if (mark && Object.keys(mark).length) {
105
- Object.assign(obj, { mark });
106
- }
107
- // 如果以上都没有,那可能就是在detail中
108
- if (detail && Object.keys(obj).length === 0) {
109
- Object.assign(obj, { detail });
110
- }
111
- return deepClone(obj);
112
- }
113
-
114
89
  export default {
115
90
  deepClone,
116
- getEventExtra,
117
91
  };
@@ -5,10 +5,6 @@
5
5
 
6
6
  // / <reference path='./types.ts'/>
7
7
 
8
- // uniapp转换工具执行之后会打开这句注释
9
- // import Vue from 'vue';
10
-
11
- import clone from '../clone';
12
8
  import helper from './helper';
13
9
 
14
10
  // 劫持Component的生命周期
@@ -21,17 +17,20 @@ function proxyLifeMethod(componentName: string, componentOptions: any, methodNam
21
17
  let original = obj[methodName] || helper.emptyFunc;
22
18
  obj[methodName] = function (...args: any[]): any {
23
19
  // 生命周期函数先发埋点,避免次过程用户退出而丢失埋点
24
- const data = clone.deepClone(this.data);
25
- // vue下组件ready事件名是mounted,这里统一改为跟小程序一样用ready
26
- const funcName = methodName === 'mounted' ? 'ready' : methodName;
27
- const eventName = `Component_${componentName}_${funcName}`;
28
- helper.reportData(eventName, data);
20
+ reportLifeEvent(this, componentName, methodName);
29
21
  // 执行原函数
30
22
  return helper.executeFunc(this, original, args, helper.emptyFunc);
31
23
  }
32
24
  /* eslint-enable */
33
25
  }
34
26
 
27
+ // 上报生命周期事件
28
+ function reportLifeEvent(instance: any, componentName: string, methodName: string): void {
29
+ const data = helper.cloneData(instance);
30
+ const eventName = `Component_${componentName}_${methodName}`;
31
+ helper.reportData(eventName, data);
32
+ }
33
+
35
34
  // 劫持绑定事件
36
35
  function proxyBindEvent(componentName: string, methods: any, methodName: string, bindType: string): void {
37
36
  const original = methods[methodName];
@@ -42,8 +41,8 @@ function proxyBindEvent(componentName: string, methods: any, methodName: string,
42
41
  methods[methodName] = function (...args: any[]): any {
43
42
  // 执行原函数之后再发埋点
44
43
  return helper.executeFunc(this, original, args, () => {
45
- const extra = clone.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
46
- const data = clone.deepClone(this.data);
44
+ const extra = helper.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
45
+ const data = helper.cloneData(this);
47
46
  const eventName = `Component_${componentName}_${methodName}`;
48
47
  helper.setLastBindEvent({ eventName, data, extra, bindType });
49
48
  helper.reportData(eventName, data, extra, bindType);
@@ -72,22 +71,39 @@ function proxyMpComponent(): void {
72
71
 
73
72
  // 劫持vue的Component
74
73
  function proxyVueComponent(): void {
74
+ const isComponent = function (options): boolean {
75
+ // options可能为空
76
+ // uniapp转换之后,Component的tmsAutoReport被放在组件属性中,而Page的被放在data中
77
+ return options?.tmsAutoReport;
78
+ };
79
+
80
+ // uniapp转换工具之后后会插入import Vue的
75
81
  // @ts-ignore
76
82
  Vue.mixin({
77
83
  beforeCreate() {
78
84
  const options = this.$options;
79
- // 有组件名则不是页面
80
- if (!options.tmsAutoReport || !options.tmsComponentName) {
85
+ if (!isComponent(options)) {
81
86
  return;
82
87
  }
83
88
 
84
89
  const { methods } = options;
90
+ if (methods.tmsReportBinded) {
91
+ return;
92
+ }
93
+ // 加个标记,避免二次挂载时重复劫持
94
+ methods.tmsReportBinded = () => {};
95
+
85
96
  for (const event of options.tmsReportEvents) {
86
97
  const { name, type } = event;
87
98
  proxyBindEvent(options.tmsComponentName, methods, name, type);
88
99
  }
100
+ },
89
101
 
90
- proxyLifeMethod(options.tmsComponentName, options, 'mounted');
102
+ mounted() {
103
+ const options = this.$options;
104
+ if (isComponent(options)) {
105
+ reportLifeEvent(this, options.tmsComponentName, 'ready');
106
+ }
91
107
  },
92
108
  });
93
109
  }
@@ -5,6 +5,8 @@
5
5
 
6
6
  // / <reference path='./types.ts'/>
7
7
 
8
+ import clone from '../clone';
9
+
8
10
  function getReporter(): any {
9
11
  // 如果是在app.js的onLaunch中调用,则没有getApp().tms为空
10
12
  const tms = getApp()?.tms || (wx as any).tms;
@@ -97,12 +99,55 @@ function executeFunc(context: any, func: Function, args: any[], callback: Functi
97
99
  });
98
100
  }
99
101
 
102
+ /**
103
+ * 复制组件的data
104
+ * @param instance 组件实例
105
+ */
106
+ function cloneData(instance: any): any {
107
+ if (!wx.isH5) {
108
+ return clone.deepClone(instance.data);
109
+ }
110
+
111
+ // 取出vue的props跟data
112
+ const data = { ...instance.$options.propsData };
113
+ if (instance.$options.data) {
114
+ Object.assign(data, instance.$options.data());
115
+ }
116
+ return clone.deepClone(data);
117
+ }
118
+
119
+ /**
120
+ * 获取触发绑定事件的携带数据
121
+ */
122
+ function getEventExtra(event: any): any {
123
+ if (!event) {
124
+ return '';
125
+ }
126
+ const { currentTarget, mark, detail } = event;
127
+ const obj = {};
128
+ // 一般把数据放在dataset或者mark中
129
+ const dataset = currentTarget?.dataset;
130
+ if (dataset && Object.keys(dataset).length) {
131
+ Object.assign(obj, { dataset });
132
+ }
133
+ if (mark && Object.keys(mark).length) {
134
+ Object.assign(obj, { mark });
135
+ }
136
+ // 如果以上都没有,那可能就是在detail中
137
+ if (detail && Object.keys(obj).length === 0) {
138
+ Object.assign(obj, { detail });
139
+ }
140
+ return clone.deepClone(obj);
141
+ }
142
+
100
143
  export default {
101
144
  emptyFunc,
145
+ cloneData,
102
146
  reportData,
103
- fastReportData,
104
147
  executeFunc,
105
148
  getSystemInfo,
149
+ getEventExtra,
150
+ fastReportData,
106
151
  getLastBindEvent,
107
152
  setLastBindEvent,
108
153
  };
@@ -5,10 +5,6 @@
5
5
 
6
6
  // / <reference path='./types.ts'/>
7
7
 
8
- // uniapp转换工具执行之后会打开这句注释
9
- // import Vue from 'vue';
10
-
11
- import clone from '../clone';
12
8
  import helper from './helper';
13
9
 
14
10
  // 工具为页面根节点插入的触摸事件
@@ -31,14 +27,19 @@ function proxyLifeMethod(pageOptions: any, methodName: string): void {
31
27
  // eslint-disable-next-line no-param-reassign
32
28
  pageOptions[methodName] = function (...args: any[]): any {
33
29
  // 生命周期函数先发埋点,避免次过程用户退出而丢失埋点
34
- const extra = getPageLifeExtra(this, methodName, args);
35
- helper.reportData(`Page_${methodName}`, extra);
30
+ reportLifeEvent(this, methodName, args);
36
31
 
37
32
  // 执行原函数
38
33
  return helper.executeFunc(this, original, args, helper.emptyFunc);
39
34
  };
40
35
  }
41
36
 
37
+ // 上报生命周期事件
38
+ function reportLifeEvent(instance: any, methodName: string, args: any[]): void {
39
+ const extra = getPageLifeExtra(instance, methodName, args);
40
+ helper.reportData(`Page_${methodName}`, extra);
41
+ }
42
+
42
43
  // 获取生命周期函数上报时的附加信息
43
44
  function getPageLifeExtra(page: any, methodName: string, args: any[]): IPageLifeExtra | IPageTouchExtra {
44
45
  /* eslint-disable */
@@ -94,10 +95,10 @@ function proxyBindEvent(pageOptions: any, methodName: string, bindType: string):
94
95
  }
95
96
  // eslint-disable-next-line no-param-reassign
96
97
  pageOptions[methodName] = function (...args: any[]): any {
97
- const extra = clone.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
98
+ const extra = helper.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
98
99
  // 执行原函数之后再发埋点
99
100
  return helper.executeFunc(this, original, args, () => {
100
- const data = clone.deepClone(this.data);
101
+ const data = helper.cloneData(this);
101
102
  const eventName = `Page_${methodName}`;
102
103
  helper.setLastBindEvent({ eventName, data, extra, bindType });
103
104
  helper.reportData(eventName, data, extra, bindType);
@@ -126,24 +127,54 @@ function proxyMpPage(): void {
126
127
 
127
128
  // 劫持vue的Page
128
129
  function proxyVuePage(): void {
129
- // @ts-ignore
130
- Vue.mixin({
130
+ const isPage = (options): boolean => {
131
+ // options可能为空
132
+ // uniapp转换之后,Component的tmsAutoReport被放在组件属性中,而Page的被放在data中
133
+ if (!options?.data) {
134
+ return false;
135
+ }
136
+
137
+ // todo: 不知为啥非我们自定义页面或组件这里会报错
138
+ try {
139
+ return options.data().tmsAutoReport;
140
+ } catch {
141
+ return false;
142
+ }
143
+ };
144
+
145
+ const mixinObj = {
131
146
  beforeCreate() {
132
147
  const options = this.$options;
133
- // 有组件名则不是页面
134
- if (!options.tmsAutoReport || options.tmsComponentName) {
148
+ if (!isPage(options)) {
135
149
  return;
136
150
  }
137
151
 
138
- for (const methodName of lifeMethods) {
139
- proxyLifeMethod(options, methodName);
152
+ const { methods } = options;
153
+ if (methods.tmsReportBinded) {
154
+ return;
140
155
  }
141
- for (const event of options.tmsReportEvents) {
156
+ // 加个标记,避免二次挂载时重复劫持
157
+ methods.tmsReportBinded = () => {};
158
+
159
+ const { tmsReportEvents } = options.data();
160
+ for (const event of tmsReportEvents) {
142
161
  const { name, type } = event;
143
- proxyBindEvent(options.methods, name, type);
162
+ proxyBindEvent(methods, name, type);
144
163
  }
145
164
  },
146
- });
165
+ };
166
+
167
+ for (const methodName of mustLifeMethods) {
168
+ mixinObj[methodName] = function (...args: any[]) {
169
+ if (isPage(this.$options)) {
170
+ reportLifeEvent(this, methodName, args);
171
+ }
172
+ };
173
+ }
174
+
175
+ // uniapp转换工具之后后会插入import Vue的
176
+ // @ts-ignore
177
+ Vue.mixin(mixinObj);
147
178
  }
148
179
 
149
180
  // 劫持Page