@tmsfe/tms-core 0.0.101 → 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.101",
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,7 +5,6 @@
5
5
 
6
6
  // / <reference path='./types.ts'/>
7
7
 
8
- import clone from '../clone';
9
8
  import helper from './helper';
10
9
 
11
10
  // 劫持Component的生命周期
@@ -18,17 +17,20 @@ function proxyLifeMethod(componentName: string, componentOptions: any, methodNam
18
17
  let original = obj[methodName] || helper.emptyFunc;
19
18
  obj[methodName] = function (...args: any[]): any {
20
19
  // 生命周期函数先发埋点,避免次过程用户退出而丢失埋点
21
- const data = clone.deepClone(this.data);
22
- // vue下组件ready事件名是mounted,这里统一改为跟小程序一样用ready
23
- const funcName = methodName === 'mounted' ? 'ready' : methodName;
24
- const eventName = `Component_${componentName}_${funcName}`;
25
- helper.reportData(eventName, data);
20
+ reportLifeEvent(this, componentName, methodName);
26
21
  // 执行原函数
27
22
  return helper.executeFunc(this, original, args, helper.emptyFunc);
28
23
  }
29
24
  /* eslint-enable */
30
25
  }
31
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
+
32
34
  // 劫持绑定事件
33
35
  function proxyBindEvent(componentName: string, methods: any, methodName: string, bindType: string): void {
34
36
  const original = methods[methodName];
@@ -39,8 +41,8 @@ function proxyBindEvent(componentName: string, methods: any, methodName: string,
39
41
  methods[methodName] = function (...args: any[]): any {
40
42
  // 执行原函数之后再发埋点
41
43
  return helper.executeFunc(this, original, args, () => {
42
- const extra = clone.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
43
- const data = clone.deepClone(this.data);
44
+ const extra = helper.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
45
+ const data = helper.cloneData(this);
44
46
  const eventName = `Component_${componentName}_${methodName}`;
45
47
  helper.setLastBindEvent({ eventName, data, extra, bindType });
46
48
  helper.reportData(eventName, data, extra, bindType);
@@ -69,22 +71,39 @@ function proxyMpComponent(): void {
69
71
 
70
72
  // 劫持vue的Component
71
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的
72
81
  // @ts-ignore
73
82
  Vue.mixin({
74
83
  beforeCreate() {
75
84
  const options = this.$options;
76
- // 有组件名则不是页面
77
- if (!options.tmsAutoReport || !options.tmsComponentName) {
85
+ if (!isComponent(options)) {
78
86
  return;
79
87
  }
80
88
 
81
89
  const { methods } = options;
90
+ if (methods.tmsReportBinded) {
91
+ return;
92
+ }
93
+ // 加个标记,避免二次挂载时重复劫持
94
+ methods.tmsReportBinded = () => {};
95
+
82
96
  for (const event of options.tmsReportEvents) {
83
97
  const { name, type } = event;
84
98
  proxyBindEvent(options.tmsComponentName, methods, name, type);
85
99
  }
100
+ },
86
101
 
87
- proxyLifeMethod(options.tmsComponentName, options, 'mounted');
102
+ mounted() {
103
+ const options = this.$options;
104
+ if (isComponent(options)) {
105
+ reportLifeEvent(this, options.tmsComponentName, 'ready');
106
+ }
88
107
  },
89
108
  });
90
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,7 +5,6 @@
5
5
 
6
6
  // / <reference path='./types.ts'/>
7
7
 
8
- import clone from '../clone';
9
8
  import helper from './helper';
10
9
 
11
10
  // 工具为页面根节点插入的触摸事件
@@ -28,14 +27,19 @@ function proxyLifeMethod(pageOptions: any, methodName: string): void {
28
27
  // eslint-disable-next-line no-param-reassign
29
28
  pageOptions[methodName] = function (...args: any[]): any {
30
29
  // 生命周期函数先发埋点,避免次过程用户退出而丢失埋点
31
- const extra = getPageLifeExtra(this, methodName, args);
32
- helper.reportData(`Page_${methodName}`, extra);
30
+ reportLifeEvent(this, methodName, args);
33
31
 
34
32
  // 执行原函数
35
33
  return helper.executeFunc(this, original, args, helper.emptyFunc);
36
34
  };
37
35
  }
38
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
+
39
43
  // 获取生命周期函数上报时的附加信息
40
44
  function getPageLifeExtra(page: any, methodName: string, args: any[]): IPageLifeExtra | IPageTouchExtra {
41
45
  /* eslint-disable */
@@ -91,10 +95,10 @@ function proxyBindEvent(pageOptions: any, methodName: string, bindType: string):
91
95
  }
92
96
  // eslint-disable-next-line no-param-reassign
93
97
  pageOptions[methodName] = function (...args: any[]): any {
94
- const extra = clone.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
98
+ const extra = helper.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
95
99
  // 执行原函数之后再发埋点
96
100
  return helper.executeFunc(this, original, args, () => {
97
- const data = clone.deepClone(this.data);
101
+ const data = helper.cloneData(this);
98
102
  const eventName = `Page_${methodName}`;
99
103
  helper.setLastBindEvent({ eventName, data, extra, bindType });
100
104
  helper.reportData(eventName, data, extra, bindType);
@@ -123,24 +127,54 @@ function proxyMpPage(): void {
123
127
 
124
128
  // 劫持vue的Page
125
129
  function proxyVuePage(): void {
126
- // @ts-ignore
127
- 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 = {
128
146
  beforeCreate() {
129
147
  const options = this.$options;
130
- // 有组件名则不是页面
131
- if (!options.tmsAutoReport || options.tmsComponentName) {
148
+ if (!isPage(options)) {
132
149
  return;
133
150
  }
134
151
 
135
- for (const methodName of lifeMethods) {
136
- proxyLifeMethod(options, methodName);
152
+ const { methods } = options;
153
+ if (methods.tmsReportBinded) {
154
+ return;
137
155
  }
138
- for (const event of options.tmsReportEvents) {
156
+ // 加个标记,避免二次挂载时重复劫持
157
+ methods.tmsReportBinded = () => {};
158
+
159
+ const { tmsReportEvents } = options.data();
160
+ for (const event of tmsReportEvents) {
139
161
  const { name, type } = event;
140
- proxyBindEvent(options.methods, name, type);
162
+ proxyBindEvent(methods, name, type);
141
163
  }
142
164
  },
143
- });
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);
144
178
  }
145
179
 
146
180
  // 劫持Page