gio-miniprogram-sdk 4.0.0 → 4.1.0

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.
Files changed (78) hide show
  1. package/dist/alipay.js +1 -1
  2. package/dist/baidu.js +1 -1
  3. package/dist/bytedance.js +1 -1
  4. package/dist/jingdong.js +1 -1
  5. package/dist/kuaishou.js +1 -1
  6. package/dist/plugins/gioABTest.js +1 -1
  7. package/dist/plugins/gioCompress.js +1 -1
  8. package/dist/plugins/gioEventAutoTracking.js +1 -1
  9. package/dist/plugins/gioImpressionTracking.js +1 -1
  10. package/dist/plugins/gioMultipleInstances.js +1 -0
  11. package/dist/qq.js +1 -1
  12. package/dist/quickapp.js +1 -1
  13. package/dist/taobao.js +1 -1
  14. package/dist/taro.js +1 -1
  15. package/dist/uniapp.js +1 -1
  16. package/dist/wechat.js +1 -1
  17. package/package.json +39 -42
  18. package/rollup.config.js +11 -6
  19. package/rollup.plugins.config.js +13 -10
  20. package/src/{pluginsOut/frameworks → adapters}/gioTaobaoAdapter.ts +47 -44
  21. package/src/adapters/gioTaroAdapter.ts +459 -0
  22. package/src/{pluginsOut/frameworks → adapters}/gioUniAppAdapter.ts +35 -6
  23. package/src/constants/config.ts +49 -20
  24. package/src/constants/emitMsg.ts +23 -0
  25. package/src/constants/regex.ts +14 -0
  26. package/src/core/dataStore/eventContextBuilder.ts +28 -17
  27. package/src/core/dataStore/eventHooks/appEffects.ts +50 -31
  28. package/src/core/dataStore/eventHooks/index.ts +7 -5
  29. package/src/core/dataStore/eventHooks/minipPage.ts +2 -11
  30. package/src/core/dataStore/eventHooks/pageEffects.ts +61 -27
  31. package/src/core/dataStore/index.ts +266 -181
  32. package/src/core/growingIO.ts +312 -179
  33. package/src/core/pluginsInstance/base.ts +157 -0
  34. package/src/core/pluginsInstance/taro.ts +15 -0
  35. package/src/core/pluginsInstance/tb.ts +15 -0
  36. package/src/core/pluginsInstance/uniapp.ts +15 -0
  37. package/src/core/uploader.ts +131 -87
  38. package/src/core/userStore.ts +160 -121
  39. package/src/index.ts +37 -28
  40. package/src/minipInstance/base.ts +2 -1
  41. package/src/minipInstance/quickapp.ts +5 -19
  42. package/src/platformConfig/base.ts +0 -4
  43. package/src/{pluginsOut/ordinary → plugins}/gioABTest.ts +74 -37
  44. package/src/{pluginsOut/ordinary → plugins}/gioEventAutoTracking.ts +25 -18
  45. package/src/{pluginsOut/ordinary → plugins}/gioImpressionTracking.ts +109 -41
  46. package/src/plugins/gioMultipleInstances.ts +176 -0
  47. package/src/types/base.ts +12 -3
  48. package/src/types/dataStore.ts +31 -16
  49. package/src/types/eventHooks.ts +8 -9
  50. package/src/types/growingIO.ts +30 -14
  51. package/src/types/platforms.ts +0 -4
  52. package/src/types/plugins.ts +1 -1
  53. package/src/types/uploader.ts +16 -12
  54. package/src/types/userStore.ts +21 -17
  55. package/src/utils/glodash.ts +10 -3
  56. package/src/utils/tools.ts +27 -6
  57. package/src/utils/verifiers.ts +25 -50
  58. package/typings/global.d.ts +5 -0
  59. package/.babelrc +0 -4
  60. package/bin/build/full.sh +0 -32
  61. package/bin/build/jd.sh +0 -14
  62. package/bin/build/ks.sh +0 -14
  63. package/bin/build/my.sh +0 -14
  64. package/bin/build/plugins.sh +0 -5
  65. package/bin/build/qq.sh +0 -14
  66. package/bin/build/quickapp.sh +0 -14
  67. package/bin/build/swan.sh +0 -14
  68. package/bin/build/taro.sh +0 -18
  69. package/bin/build/tb.sh +0 -18
  70. package/bin/build/tt.sh +0 -14
  71. package/bin/build/uniapp.sh +0 -18
  72. package/bin/build/wx.sh +0 -14
  73. package/src/core/plugins.ts +0 -152
  74. package/src/pluginsOut/README.md +0 -50
  75. package/src/pluginsOut/frameworks/gioTaroAdapter.ts +0 -358
  76. package/src/pluginsOut/ordinary/gioCustomTracking.ts +0 -71
  77. package/bin/{build/all.sh → build.sh} +3 -3
  78. /package/src/{pluginsOut/ordinary → plugins}/gioCompress.ts +0 -0
@@ -2,15 +2,17 @@
2
2
  * 名称:淘宝小程序单发插件
3
3
  * 用途:用于提供淘宝小程序云函数和云应用的请求方法。
4
4
  */
5
- import { Event } from '@@/types/base';
5
+ import { EVENT, EXTEND_EVENT } from '@@/types/base';
6
6
  import { GrowingIOType } from '@@/types/growingIO';
7
+ import { head, unset } from '@@/utils/glodash';
8
+ import EMIT_MSG from '@@/constants/emitMsg';
7
9
 
8
10
  let ut;
9
11
  class GioTaobaoAdapter {
10
12
  constructor(public growingIO: GrowingIOType) {
11
13
  const { utils, emitter } = this.growingIO;
12
14
  ut = utils;
13
- emitter.on('OPTION_INITIALIZED', (growingIO: GrowingIOType) => {
15
+ emitter.on(EMIT_MSG.OPTION_INITIALIZED, (growingIO: GrowingIOType) => {
14
16
  const { inPlugin, dataStore } = growingIO;
15
17
  if (inPlugin) {
16
18
  ut.getGlobal().Component = function (...args: any[]) {
@@ -18,7 +20,7 @@ class GioTaobaoAdapter {
18
20
  };
19
21
  }
20
22
  });
21
- emitter.on('minipLifecycle', ({ event }) => {
23
+ emitter.on(EMIT_MSG.MINIP_LIFECYCLE, ({ event }) => {
22
24
  const { dataStore, vdsConfig } = this.growingIO;
23
25
  const widgetName = `小部件${vdsConfig.appId}`;
24
26
  switch (event) {
@@ -30,10 +32,12 @@ class GioTaobaoAdapter {
30
32
  .map((k) => `${k}=${relationAppInfo[k]}`)
31
33
  .join('&');
32
34
  dataStore.scene = sceneInfo.sceneId ?? '';
33
- dataStore.sendVisit({
34
- path: widgetName,
35
- query,
36
- title: widgetName
35
+ dataStore.trackersExecute((trackingId: string) => {
36
+ dataStore.sendVisit(trackingId, {
37
+ path: widgetName,
38
+ query,
39
+ title: widgetName
40
+ });
37
41
  });
38
42
  };
39
43
  this.getRelationAppInfo((relationAppInfo: any) =>
@@ -42,9 +46,14 @@ class GioTaobaoAdapter {
42
46
  }
43
47
  break;
44
48
  case 'Page didMount':
45
- dataStore.sendPage({
46
- path: widgetName,
47
- title: widgetName
49
+ dataStore.trackersExecute((trackingId: string) => {
50
+ const { trackPage } = dataStore.getTrackerVds(trackingId);
51
+ if (trackPage) {
52
+ dataStore.sendPage(trackingId, {
53
+ path: widgetName,
54
+ title: widgetName
55
+ });
56
+ }
48
57
  });
49
58
  break;
50
59
  default:
@@ -70,30 +79,31 @@ class GioTaobaoAdapter {
70
79
  };
71
80
 
72
81
  // 单条发送无延迟
73
- singleInvoke = () => {
82
+ singleInvoke = (trackingId: string) => {
74
83
  const { vdsConfig, emitter, uploader } = this.growingIO;
84
+ const hoardingQueue = uploader.getHoardingQueue(trackingId);
85
+ const requestQueue = uploader.getRequestQueue(trackingId);
75
86
  // 过滤掉重试超过3次的请求(直接丢弃)
76
- uploader.hoardingQueue = [...uploader.hoardingQueue].filter(
77
- (o) => (uploader.retryIds[o.requestId] || 0) < uploader.retryLimit
78
- );
79
- uploader.requestQueue = [...uploader.requestQueue].filter(
87
+ uploader.requestQueue[trackingId] = [...requestQueue].filter(
80
88
  (o) => (uploader.retryIds[o.requestId] || 0) < uploader.retryLimit
81
89
  );
82
- if (ut.isEmpty([...uploader.hoardingQueue, ...uploader.requestQueue])) {
90
+ if (ut.isEmpty([...hoardingQueue, ...requestQueue])) {
83
91
  return;
84
92
  }
85
- let requestData =
86
- uploader.hoardingQueue.shift() ?? uploader.requestQueue.shift();
93
+ const eventData: EXTEND_EVENT =
94
+ hoardingQueue.shift() ?? requestQueue.shift();
95
+ let requestData = { ...eventData };
96
+ unset(requestData, ['requestId', 'trackingId']);
87
97
  // 开启debug模式时,打印事件日志
88
98
  if (vdsConfig.debug) {
89
99
  console.log('[GrowingIO Debug]:', JSON.stringify(requestData, null, 2));
90
100
  }
91
- emitter.emit('onSendBefore', { requestData });
92
- this.cloudFuncInvoke(requestData);
101
+ emitter.emit(EMIT_MSG.ON_SEND_BEFORE, { requestData });
102
+ this.cloudFuncInvoke(eventData, requestData);
93
103
  };
94
104
 
95
105
  // 云函数调用
96
- cloudFuncInvoke = (requestData) => {
106
+ cloudFuncInvoke = (eventData: EXTEND_EVENT, requestData: EVENT) => {
97
107
  const { vdsConfig, emitter, uploader } = this.growingIO;
98
108
  const { serverUrl, projectId, tbConfig } = vdsConfig;
99
109
  const app = ut.niceTry(() => getApp() ?? $global);
@@ -115,18 +125,18 @@ class GioTaobaoAdapter {
115
125
  uploader.requestingNum -= 1;
116
126
  // 这里的返回值只是调用了api是否成功,真正是否上报成功不知道,要去淘宝控制台看
117
127
  if (res.success) {
118
- emitter.emit('onSendAfter', { result: res });
128
+ emitter.emit(EMIT_MSG.ON_SEND_AFTER, { result: res, requestData });
119
129
  } else {
120
- uploader.requestFailFn(requestData);
130
+ uploader.requestFailFn(eventData);
121
131
  ut.consoleText(`请求失败! ${JSON.stringify(res)}`, 'error');
122
132
  }
123
- uploader.initiateRequest();
133
+ uploader.initiateRequest(eventData.trackingId);
124
134
  })
125
135
  .catch((e) => {
126
136
  uploader.requestingNum -= 1;
127
- uploader.requestFailFn(requestData);
137
+ uploader.requestFailFn(eventData);
128
138
  ut.consoleText(`请求失败! ${JSON.stringify(e)}`, 'error');
129
- uploader.initiateRequest();
139
+ uploader.initiateRequest(eventData.trackingId);
130
140
  });
131
141
  } else {
132
142
  ut.consoleText(
@@ -137,12 +147,13 @@ class GioTaobaoAdapter {
137
147
  };
138
148
 
139
149
  // 云应用调用
140
- tbCloudAppInvoke(requestData) {
150
+ tbCloudAppInvoke(eventsQueue: EXTEND_EVENT[], requestData: EVENT) {
141
151
  const { vdsConfig, emitter, uploader } = this.growingIO;
142
152
  const { serverUrl, projectId, tbConfig } = vdsConfig;
143
153
  const app = ut.niceTry(() => getApp() ?? $global);
144
154
  const cloud = tbConfig.cloud ?? app.cloud;
145
155
  if (cloud?.application?.httpRequest) {
156
+ const trackingId = head(eventsQueue).trackingId;
146
157
  uploader.requestingNum += 1;
147
158
  cloud.application
148
159
  .httpRequest({
@@ -158,30 +169,22 @@ class GioTaobaoAdapter {
158
169
  uploader.requestingNum -= 1;
159
170
  // 这里的返回值只是调用了api是否成功,真正是否上报成功不知道,要看云应用的服务端是不是真的转发成功
160
171
  if (res.success) {
161
- emitter.emit('onSendAfter', { result: res });
172
+ emitter.emit(EMIT_MSG.ON_SEND_AFTER, { result: res, requestData });
162
173
  } else {
163
- if (ut.isArray(requestData)) {
164
- requestData.forEach((o: any) => {
165
- uploader.requestFailFn(o);
166
- });
167
- } else {
168
- uploader.requestFailFn(requestData);
169
- }
174
+ eventsQueue.forEach((o: any) => {
175
+ uploader.requestFailFn(o);
176
+ });
170
177
  ut.consoleText(`请求失败! ${JSON.stringify(res)}`, 'error');
171
178
  }
172
- uploader.initiateRequest();
179
+ uploader.initiateRequest(trackingId);
173
180
  })
174
181
  .catch((e) => {
175
182
  uploader.requestingNum -= 1;
176
- if (ut.isArray(requestData)) {
177
- requestData.forEach((o: any) => {
178
- uploader.requestFailFn(o);
179
- });
180
- } else {
181
- uploader.requestFailFn(requestData);
182
- }
183
+ eventsQueue.forEach((o: any) => {
184
+ uploader.requestFailFn(o);
185
+ });
183
186
  ut.consoleText(`请求失败! ${JSON.stringify(e)}`, 'error');
184
- uploader.initiateRequest();
187
+ uploader.initiateRequest(trackingId);
185
188
  });
186
189
  } else {
187
190
  ut.consoleText(
@@ -0,0 +1,459 @@
1
+ /**
2
+ * 名称:Taro代理插件
3
+ * 用途:用于重写Taro框架下的创建App/Page/Component方法实现代理Hook;并获取Taro框架下的自定义方法真实方法名获取。
4
+ * 注意:测试taro3react时,微信要用react18测试,支付宝要用react17测试。
5
+ */
6
+ import {
7
+ TARO_EVENT_PROPS_REG,
8
+ TARO_EVENT_REACT_FUNC1_REG,
9
+ TARO_EVENT_REACT_FUNC2_REG,
10
+ TARO_EVENT_VUE_FUNC1_REG,
11
+ TARO_EVENT_VUE_FUNC2_REG,
12
+ TARO_EVENT_VUE_FUNC3_REG
13
+ } from '@@/constants/regex';
14
+ import { GrowingIOType } from '@@/types/growingIO';
15
+ import EMIT_MSG from '@@/constants/emitMsg';
16
+
17
+ let ut;
18
+ const HANDLER = {
19
+ tap: 'onClick',
20
+ longpress: 'onLongPress'
21
+ };
22
+ const CUSTOM_HOOK_EVENTS = [
23
+ 'onShareAppMessage',
24
+ 'onShareTimeline',
25
+ 'onAddToFavorites',
26
+ 'onTabItemTap'
27
+ ];
28
+ class GioTaroAdapter {
29
+ public taroVersion: string;
30
+ private taro: any;
31
+ private taroVue: any;
32
+ private taroVueVersion: number;
33
+ private exposedNames: any;
34
+ constructor(public growingIO: GrowingIOType) {
35
+ const { utils, emitter, minipInstance } = this.growingIO;
36
+ ut = utils;
37
+ this.exposedNames = {};
38
+ emitter.on(EMIT_MSG.MINIP_LIFECYCLE, ({ event }) => {
39
+ if (['Page onShow', 'Page onReady'].includes(event)) {
40
+ if (this.taro && this.taroVersion === '3') {
41
+ // 提前存储页面节点信息用来获取dataset
42
+ this.saveFullPage(document.body);
43
+ // taro3开发时要等onready才能取到节点,所以补充做一次曝光监听
44
+ setTimeout(
45
+ () => minipInstance.initImpression(minipInstance.getCurrentPage()),
46
+ 0
47
+ );
48
+ }
49
+ }
50
+ });
51
+ }
52
+
53
+ // 主入口,版本判断
54
+ main = () => {
55
+ const { taro, taroVue } = this.growingIO.vdsConfig;
56
+ const { Current, createComponent } = taro;
57
+ const isTaro2 = !Current && createComponent;
58
+ const isTaro3 = Current && !createComponent;
59
+ this.taro = taro;
60
+ if (isTaro2) {
61
+ // taro2
62
+ this.taroVersion = '2';
63
+ this.proxyTaro2(this.taro);
64
+ ut.consoleText('Taro version 2', 'info');
65
+ } else if (isTaro3) {
66
+ // taro3
67
+ this.taroVersion = '3';
68
+ this.taroVue = taroVue;
69
+ if (this.taroVue) {
70
+ const mainVersion = Number(
71
+ ut.head(ut.split(this.taroVue.version, '.'))
72
+ );
73
+ this.taroVueVersion = mainVersion;
74
+ ut.consoleText(`Taro version 3, Vue version ${mainVersion}`, 'info');
75
+ } else {
76
+ ut.consoleText('Taro version 3', 'info');
77
+ }
78
+ this.proxyTaro3();
79
+ } else {
80
+ ut.consoleText('未获取到Taro实例或不支持的Taro版本,请检查!', 'error');
81
+ }
82
+ };
83
+
84
+ // 代理taro2
85
+ proxyTaro2 = (taro: any) => {
86
+ const self = this;
87
+ const originApp = taro.createApp;
88
+ const originComponent = taro.createComponent;
89
+ if (originApp) {
90
+ taro.createApp = function (AppClass) {
91
+ const AppRef = originApp(AppClass);
92
+ self.growingIO.dataStore.eventHooks.appOverriding(AppRef);
93
+ return AppRef;
94
+ };
95
+ }
96
+ if (originComponent) {
97
+ taro.createComponent = function (ComponentClass, isPage) {
98
+ const ComponentRef = originComponent(ComponentClass, isPage);
99
+ const targetType = isPage ? 'page' : 'component';
100
+ // wx/qq的生命周期函数和自定义函数都在ComponentRef.methods中
101
+ // my/tt/jd的生命周期函数和自定义函数都在ComponentRef中
102
+ // swan的生命周期函数在ComponentRef.methods中,自定义函数在ComponentRef中
103
+ switch (self.growingIO.gioPlatform) {
104
+ case 'wx':
105
+ case 'qq':
106
+ self.growingIO.dataStore.eventHooks[`${targetType}Overriding`](
107
+ ComponentRef.methods
108
+ );
109
+ break;
110
+ case 'my':
111
+ case 'tt':
112
+ case 'jd':
113
+ self.growingIO.dataStore.eventHooks[`${targetType}Overriding`](
114
+ ComponentRef
115
+ );
116
+ break;
117
+ case 'swan':
118
+ self.growingIO.dataStore.eventHooks[`${targetType}Overriding`](
119
+ ComponentRef
120
+ );
121
+ self.growingIO.dataStore.eventHooks[`${targetType}Overriding`](
122
+ ComponentRef.methods
123
+ );
124
+ break;
125
+ default:
126
+ break;
127
+ }
128
+ return ComponentRef;
129
+ };
130
+ }
131
+ };
132
+
133
+ // 代理taro3
134
+ proxyTaro3 = () => {
135
+ const self = this;
136
+ const {
137
+ dataStore: { eventHooks },
138
+ minipInstance
139
+ } = this.growingIO;
140
+ // hook app
141
+ eventHooks.nativeGrowing(['App']);
142
+ // taro3vue2走单独的hook逻辑
143
+ if (this.taroVueVersion === 2) {
144
+ eventHooks.nativeGrowing(['Page']);
145
+ this.taro3Vue2Proxy();
146
+ return;
147
+ }
148
+ if (this.taroVueVersion === 3) {
149
+ this.proxyTaro3vue3();
150
+ }
151
+ // taro3react / taro3vue3走监听hook逻辑
152
+ const originCall = self.taro?.hooks?.call;
153
+ if (originCall) {
154
+ self.defineProperty(self.taro.hooks, 'call', function (...args) {
155
+ const argsArray = Array.from(args);
156
+ let result = originCall.apply(this, argsArray);
157
+ // 根据taro消息直接触发页面生命周期
158
+ if (argsArray[0] === 'getLifecycle') {
159
+ const lifetime = argsArray[2];
160
+ if (
161
+ eventHooks.pageHandlers.includes(lifetime) &&
162
+ !CUSTOM_HOOK_EVENTS.includes(lifetime)
163
+ ) {
164
+ ut.niceTry(() =>
165
+ eventHooks.pageEffects.main(
166
+ minipInstance.getCurrentPage(),
167
+ lifetime,
168
+ argsArray[1]
169
+ )
170
+ );
171
+ }
172
+ }
173
+ // 分享和添加收藏事件走hook逻辑
174
+ if (argsArray[0] === 'modifyPageObject') {
175
+ const pageObject = argsArray[1];
176
+ CUSTOM_HOOK_EVENTS.forEach((k) => {
177
+ if (pageObject[k]) {
178
+ pageObject[k] = eventHooks.lifeFcEffects(
179
+ k,
180
+ ut.isFunction(pageObject[k]) ? pageObject[k] : () => {},
181
+ 'Page'
182
+ );
183
+ }
184
+ });
185
+ }
186
+ // 无埋点事件
187
+ if (argsArray[0] === 'dispatchTaroEvent') {
188
+ const taroEvent = argsArray[1];
189
+ const taroElement = argsArray[2];
190
+ const actionEffects =
191
+ self.growingIO.plugins?.gioEventAutoTracking?.main;
192
+ if (
193
+ ut.isFunction(actionEffects) &&
194
+ eventHooks.actionEventTypes.includes(taroEvent.type)
195
+ ) {
196
+ const { currentTarget, target, detail } = taroEvent.mpEvent;
197
+ // taro本身会给所有节点添加id,id一致说明是触发事件的节点
198
+ if (target.id === currentTarget.id) {
199
+ // 尝试获取真实的方法名
200
+ try {
201
+ let originHandler = ut.head(
202
+ taroElement.__handlers[taroEvent.type]
203
+ );
204
+ // 一定要有对应的事件
205
+ if (originHandler) {
206
+ if (originHandler.oldHandler) {
207
+ originHandler = originHandler.oldHandler;
208
+ }
209
+ let funcName = '';
210
+ if (self.taroVue) {
211
+ // vue3
212
+ funcName = self.taro3vue3GetFuncName(
213
+ originHandler,
214
+ taroElement
215
+ );
216
+ } else {
217
+ // react --- @tarojs/runtime 3.6.x会有一个随机名的对象存储点击事件优先获取,其他版本直接取originHandler
218
+ funcName = self.taro3reactGetFuncName(
219
+ originHandler,
220
+ taroEvent,
221
+ taroElement
222
+ );
223
+ }
224
+
225
+ // 构建无埋点事件
226
+ actionEffects(
227
+ {
228
+ ...taroEvent.mpEvent,
229
+ currentTarget: {
230
+ ...currentTarget,
231
+ detail,
232
+ dataset: {
233
+ ...currentTarget.dataset,
234
+ ...taroElement.dataset
235
+ }
236
+ }
237
+ },
238
+ funcName
239
+ );
240
+ }
241
+ } catch (error) {
242
+ ut.consoleText('Error: ' + error, 'error');
243
+ }
244
+ }
245
+ }
246
+ }
247
+ return result;
248
+ });
249
+ } else {
250
+ ut.consoleText('Taro3实例获取失败,请检查初始化逻辑!', 'warn');
251
+ eventHooks.nativeGrowing(['Page']);
252
+ }
253
+ };
254
+
255
+ // 保存vue3下使用setup写法的function component的导出方法名
256
+ proxyTaro3vue3 = () => {
257
+ const self = this;
258
+ this.taroVue.mixin({
259
+ beforeMount: function () {
260
+ // 存在tid说明是页面
261
+ if (this._?.props?.tid && !ut.isEmpty(this._.exposed)) {
262
+ const path = ut.head(ut.split(this._.props.tid, '?'));
263
+ const kvs = {};
264
+ ut.keys(this._.exposed).forEach((k) => {
265
+ if (this._.exposed[k].name) {
266
+ kvs[this._.exposed[k].name] = k;
267
+ }
268
+ });
269
+ self.exposedNames[path] = { ...kvs };
270
+ }
271
+ }
272
+ });
273
+ };
274
+
275
+ // taro3react获取方法名
276
+ taro3reactGetFuncName = (
277
+ originHandler: any,
278
+ taroEvent: any,
279
+ taroElement: any
280
+ ) => {
281
+ const propsKey = ut
282
+ .keys(taroElement)
283
+ .find((key) => TARO_EVENT_PROPS_REG.test(key));
284
+ const propsHandler =
285
+ ut.niceTry(() => taroElement[propsKey][HANDLER[taroEvent.type]]) ??
286
+ originHandler.oldHandler ??
287
+ originHandler;
288
+ if (propsHandler?.value?.name) {
289
+ return propsHandler?.value?.name;
290
+ } else if (
291
+ propsHandler.name &&
292
+ !['handler', 'invoker'].includes(propsHandler.name)
293
+ ) {
294
+ // class component匿名引用方法
295
+ let funcName = ut
296
+ .head(`${propsHandler}`.match(TARO_EVENT_REACT_FUNC1_REG))
297
+ ?.replace('return ', '')
298
+ ?.replace('(', '');
299
+ if (funcName) {
300
+ return ut.head(ut.drop(ut.split(funcName, '.'))) ?? propsHandler.name;
301
+ } else {
302
+ // component匿名引用方法
303
+ funcName = ut
304
+ .head(`${propsHandler}`.match(TARO_EVENT_REACT_FUNC2_REG))
305
+ ?.replace('return ', '')
306
+ ?.replace('(', '');
307
+ return funcName ?? propsHandler.name;
308
+ }
309
+ } else {
310
+ return this.getAnonymousFunc(taroElement);
311
+ }
312
+ };
313
+
314
+ // taro3vue3获取方法名
315
+ taro3vue3GetFuncName = (originHandler: any, taroElement: any) => {
316
+ if (ut.startsWith(`${originHandler.value}`.replace(' ', ''), 'function(')) {
317
+ // 使用emit监听组件的方法
318
+ let preFuncName = ut
319
+ .head(`${originHandler.value}`.match(TARO_EVENT_VUE_FUNC1_REG))
320
+ ?.replace('return ', '');
321
+ try {
322
+ // 使用emit监听组件的方法要优先判断
323
+ if (preFuncName) {
324
+ // dev状态时是单引号
325
+ // eslint-disable-next-line
326
+ if (preFuncName.indexOf("'") > -1) {
327
+ // eslint-disable-next-line
328
+ preFuncName = ut.head(ut.drop(ut.split(preFuncName, "'")));
329
+ } else {
330
+ // build状态时是双引号
331
+ preFuncName = ut.head(ut.drop(ut.split(preFuncName, '"')));
332
+ }
333
+ } else {
334
+ // 普通引用方法/匿名引用方法/普通setup定义的方法
335
+ preFuncName = ut
336
+ .head(`${originHandler.value}`.match(TARO_EVENT_VUE_FUNC2_REG))
337
+ ?.replace('return ', '');
338
+ // script setup定义且匿名引用的方法(需要配合defineExpose导出,否则是一个编译后的匿名单字母函数名)
339
+ if (!preFuncName) {
340
+ preFuncName = ut
341
+ .head(`${originHandler.value}`.match(TARO_EVENT_VUE_FUNC3_REG))
342
+ ?.replace('return ', '');
343
+ }
344
+ // script setup定义普通引用的方法(需要配合defineExpose导出,否则是一个编译后的匿名单字母函数名)
345
+ if (!preFuncName) {
346
+ preFuncName = originHandler.value?.name;
347
+ }
348
+ }
349
+ } catch (error) {
350
+ preFuncName = '';
351
+ }
352
+ // 能获取到方法名
353
+ if (preFuncName) {
354
+ let funcName =
355
+ preFuncName.indexOf('.') > -1
356
+ ? ut.head(ut.drop(ut.split(preFuncName, '.')))
357
+ : preFuncName;
358
+ let path = '';
359
+ if (taroElement?._root?.uid) {
360
+ path = ut.head(ut.split(taroElement._root.uid, '?'));
361
+ } else {
362
+ path = this.growingIO.dataStore.eventHooks.currentPage.path;
363
+ }
364
+ if (this.exposedNames[path]) {
365
+ funcName =
366
+ ut.niceTry(() => this.exposedNames[path][funcName]) ?? funcName;
367
+ }
368
+ return funcName;
369
+ } else {
370
+ // 不能获取方法名,直接构建一个匿名方法名
371
+ return this.getAnonymousFunc(taroElement);
372
+ }
373
+ } else if (originHandler?.value?.name) {
374
+ return originHandler.value.name;
375
+ } else {
376
+ return this.getAnonymousFunc(taroElement);
377
+ }
378
+ };
379
+
380
+ // 无法获取的方法名
381
+ getAnonymousFunc = (taroElement: any) => {
382
+ const { path } = this.growingIO.dataStore.eventHooks.currentPage;
383
+ const paths = path.split('/');
384
+ const idx = paths.findIndex((v) => v.indexOf('page') > -1) + 1;
385
+ const pageName = idx && paths[idx] ? paths[idx] : ut.last(paths);
386
+ return `${pageName}_Func${
387
+ ut.startsWith(taroElement.uid, '_')
388
+ ? taroElement.uid
389
+ : '_' + taroElement.uid
390
+ }`;
391
+ };
392
+
393
+ // taro3使用vue2的代理
394
+ taro3Vue2Proxy = () => {
395
+ const self = this;
396
+ this.taroVue.mixin({
397
+ beforeMount: function () {
398
+ // 对传统methods写法的普通事件hook
399
+ const methods = this.$options.methods;
400
+ ut.keys(methods).forEach((k: string) => {
401
+ self.defineProperty(this, k, self.proxyMethods(k, this[k]));
402
+ });
403
+ // 对setup中定义的事件hook
404
+ const setupState = this._setupState;
405
+ if (!ut.isEmpty(setupState)) {
406
+ ut.keys(setupState).forEach((k: string) => {
407
+ self.defineProperty(
408
+ setupState,
409
+ k,
410
+ self.proxyMethods(k, setupState[k])
411
+ );
412
+ });
413
+ }
414
+ }
415
+ });
416
+ };
417
+
418
+ // 重写方法
419
+ proxyMethods = (name: string, method: any) => {
420
+ const { eventHooks } = this.growingIO.dataStore;
421
+ if (ut.isFunction(method) && !eventHooks.pageHandlers.includes(name)) {
422
+ return function (...args) {
423
+ return eventHooks.customFcEffects(name, method).apply(this, args);
424
+ };
425
+ } else {
426
+ return method;
427
+ }
428
+ };
429
+
430
+ // 重新定义属性
431
+ defineProperty = (target, key, value) => {
432
+ Object.defineProperty(target, key, {
433
+ writable: true,
434
+ enumerable: true,
435
+ configurable: true,
436
+ value
437
+ });
438
+ };
439
+
440
+ // taro3中存储当前页面完整的数据以获取曝光事件中的dataset
441
+ // https://taro-docs.jd.com/taro/docs/react-overall#dataset
442
+ saveFullPage = (body: any) => {
443
+ const pageTraverse = (tEle: any) => {
444
+ tEle.forEach((cEle: any) => {
445
+ if (cEle?.ctx?.route) {
446
+ if (!this.growingIO.taro3VMs) {
447
+ this.growingIO.taro3VMs = {};
448
+ }
449
+ this.growingIO.taro3VMs[cEle.ctx.route] = cEle;
450
+ } else if (ut.isArray(cEle.childNodes)) {
451
+ pageTraverse(cEle.childNodes);
452
+ }
453
+ });
454
+ };
455
+ pageTraverse(body.childNodes);
456
+ };
457
+ }
458
+
459
+ export default { name: 'gioTaroAdapter', method: GioTaroAdapter };