gio-miniprogram-sdk 4.3.2 → 4.4.1
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/.github/workflows/publish.yml +3 -3
- package/dist/alipay.js +1 -1
- package/dist/baidu.js +1 -1
- package/dist/bytedance.js +1 -1
- package/dist/jingdong.js +1 -1
- package/dist/kuaishou.js +1 -1
- package/dist/plugins/gioABTest.js +1 -1
- package/dist/plugins/gioCompress.js +1 -1
- package/dist/plugins/gioEventAutoTracking.js +1 -1
- package/dist/plugins/gioImpressionTracking.js +1 -1
- package/dist/plugins/gioMultipleInstances.js +1 -1
- package/dist/plugins/gioPerformance.js +1 -0
- package/dist/qq.js +1 -1
- package/dist/quickapp.js +1 -1
- package/dist/taobao.js +1 -1
- package/dist/taro.js +1 -1
- package/dist/uniapp.js +1 -1
- package/dist/wechat.js +1 -1
- package/dist/xiaohongshu.js +1 -0
- package/package.json +12 -6
- package/rollup.config.js +9 -6
- package/rollup.plugins.config.js +1 -1
- package/src/adapters/gioUniAppAdapter.ts +324 -113
- package/src/constants/emitMsg.ts +1 -0
- package/src/core/dataStore/eventHooks/appEffects.ts +6 -1
- package/src/core/dataStore/eventHooks/index.ts +122 -80
- package/src/core/dataStore/eventHooks/minipPage.ts +78 -68
- package/src/core/dataStore/eventHooks/pageEffects.ts +9 -2
- package/src/core/dataStore/index.ts +1 -1
- package/src/core/growingIO.ts +27 -3
- package/src/core/uploader.ts +12 -3
- package/src/core/userStore.ts +1 -2
- package/src/minipInstance/base.ts +62 -23
- package/src/minipInstance/framework.ts +3 -1
- package/src/minipInstance/my.ts +34 -1
- package/src/minipInstance/quickapp.ts +11 -0
- package/src/minipInstance/wx.ts +15 -0
- package/src/minipInstance/xhs.ts +20 -0
- package/src/platformConfig/base.ts +1 -0
- package/src/platformConfig/framework.ts +2 -0
- package/src/platformConfig/my.ts +1 -0
- package/src/platformConfig/xhs.ts +27 -0
- package/src/plugins/gioABTest.ts +32 -3
- package/src/plugins/gioEventAutoTracking.ts +101 -1
- package/src/plugins/gioImpressionTracking.ts +8 -3
- package/src/plugins/gioPerformance/exception.ts +152 -0
- package/src/plugins/gioPerformance/monitor.ts +284 -0
- package/src/plugins/gioPerformance/network.ts +197 -0
- package/src/plugins/gioPerformance.ts +131 -0
- package/src/types/base.ts +5 -1
- package/src/types/eventHooks.ts +5 -4
- package/src/types/minipInstance.ts +8 -1
- package/src/types/platforms.ts +3 -0
- package/src/utils/tools.ts +47 -3
- package/src/utils/verifiers.ts +4 -3
- package/tsconfig.json +1 -1
- package/typings/global.d.ts +8 -0
- package/bin/build.sh +0 -38
package/rollup.plugins.config.js
CHANGED
|
@@ -16,7 +16,7 @@ const processENV = process.argv[process.argv.length - 1]
|
|
|
16
16
|
.split('-')
|
|
17
17
|
.filter((o) => o);
|
|
18
18
|
// 获取是否打包全量插件
|
|
19
|
-
const folder = processENV[0]
|
|
19
|
+
const folder = processENV[0] ? processENV[0] : 'plugins';
|
|
20
20
|
|
|
21
21
|
// 获取外置插件的目录
|
|
22
22
|
const plugInFolder = fs
|
|
@@ -5,93 +5,200 @@
|
|
|
5
5
|
import { UNIAPP_FUNC_REG } from '@@/constants/regex';
|
|
6
6
|
import { GrowingIOType } from '@@/types/growingIO';
|
|
7
7
|
|
|
8
|
-
const ONCE = '~';
|
|
9
|
-
const CUSTOM = '^';
|
|
10
|
-
|
|
8
|
+
const ONCE = '~'; // 用于标记一次性事件
|
|
9
|
+
const CUSTOM = '^'; // 用于标记自定义事件
|
|
10
|
+
|
|
11
|
+
let ut: any;
|
|
12
|
+
|
|
11
13
|
class GioUniAppAdapter {
|
|
12
|
-
public pluginVersion: string;
|
|
13
|
-
private uniVue: any;
|
|
14
|
-
private exposedNames:
|
|
14
|
+
public pluginVersion: string; // 插件版本号
|
|
15
|
+
private uniVue: any; // UniApp框架的Vue实例
|
|
16
|
+
private exposedNames: Record<string, string>; // 存储<script setup>中暴露的方法名映射
|
|
17
|
+
|
|
15
18
|
constructor(public growingIO: GrowingIOType) {
|
|
16
|
-
this.pluginVersion = '__PLUGIN_VERSION__';
|
|
17
|
-
ut = this.growingIO.utils;
|
|
18
|
-
this.uniVue = this.growingIO?.vdsConfig?.uniVue;
|
|
19
|
-
this.exposedNames = {};
|
|
19
|
+
this.pluginVersion = '__PLUGIN_VERSION__'; // 插件版本占位符,会在构建时替换
|
|
20
|
+
ut = this.growingIO.utils; // 初始化工具类
|
|
21
|
+
this.uniVue = this.growingIO?.vdsConfig?.uniVue; // 获取UniApp的Vue实例
|
|
22
|
+
this.exposedNames = {}; // 初始化方法名映射对象
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
/**
|
|
26
|
+
* 主入口,根据Vue版本进行不同处理
|
|
27
|
+
* 针对Vue2和Vue3采用不同的代理策略
|
|
28
|
+
*/
|
|
29
|
+
main = (): void => {
|
|
30
|
+
// 插件挂载时可能还没取到Vue实例
|
|
25
31
|
if (!this.uniVue) {
|
|
26
32
|
this.uniVue = this.growingIO?.vdsConfig?.uniVue;
|
|
27
33
|
}
|
|
28
34
|
console.log('Vue version: ', this.uniVue.version);
|
|
35
|
+
|
|
36
|
+
// 提取主版本号
|
|
29
37
|
const mainVersion = Number(ut.head(ut.split(this.uniVue.version, '.')));
|
|
30
38
|
switch (mainVersion) {
|
|
31
39
|
case 2:
|
|
32
|
-
this.
|
|
40
|
+
this.uniVue2Proxy();
|
|
33
41
|
break;
|
|
34
42
|
case 3:
|
|
35
43
|
this.uniVue3Proxy(this.uniVue);
|
|
36
44
|
break;
|
|
37
45
|
default:
|
|
46
|
+
// 不支持的版本
|
|
38
47
|
ut.consoleText('不支持的Vue版本,请使用 Vue2 或 Vue3!', 'error');
|
|
39
48
|
break;
|
|
40
49
|
}
|
|
41
50
|
};
|
|
42
51
|
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
/**
|
|
53
|
+
* 获取自定义真实的方法名
|
|
54
|
+
* 用于将框架编译后的方法名映射回用户定义的原始方法名
|
|
55
|
+
* @param eventName 事件名称
|
|
56
|
+
* @param e 事件对象
|
|
57
|
+
* @returns 真实的方法名
|
|
58
|
+
*/
|
|
59
|
+
getHandlerName = (eventName: string, e: any): string => {
|
|
45
60
|
if (eventName === '__e') {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const dataSet = currentTarget?.dataset || target?.dataset;
|
|
49
|
-
if (dataSet) {
|
|
50
|
-
const eventOpts = dataSet.eventOpts || dataSet['event-opts'];
|
|
51
|
-
const matchedEventType = (eventType: string, optType: string) =>
|
|
52
|
-
eventType === optType ||
|
|
53
|
-
(optType === 'regionchange' &&
|
|
54
|
-
(eventType === 'begin' || eventType === 'end'));
|
|
55
|
-
if (eventOpts) {
|
|
56
|
-
eventOpts.forEach((o: any[]) => {
|
|
57
|
-
let eType = ut.head(o);
|
|
58
|
-
const isCustom = eType.charAt(0) === CUSTOM;
|
|
59
|
-
eType = isCustom ? eType.slice(1) : type;
|
|
60
|
-
const isOnce = eType.charAt(0) === ONCE;
|
|
61
|
-
eType = isOnce ? eType.slice(1) : type;
|
|
62
|
-
const eArray = ut.last(o);
|
|
63
|
-
if (matchedEventType(type, eType)) {
|
|
64
|
-
methodName = ut.head(ut.head(eArray));
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return methodName;
|
|
61
|
+
// 内置事件,需要从事件对象提取真实方法名
|
|
62
|
+
return this.getEventHandlerNameFromE(e);
|
|
70
63
|
} else if (!ut.isEmpty(this.exposedNames)) {
|
|
64
|
+
// 从exposedNames中查找映射关系
|
|
71
65
|
return this.exposedNames[eventName] ?? eventName;
|
|
72
66
|
} else {
|
|
67
|
+
// 无需映射,直接返回
|
|
73
68
|
return eventName;
|
|
74
69
|
}
|
|
75
70
|
};
|
|
76
71
|
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
/**
|
|
73
|
+
* 从事件对象中获取处理函数的真实名称
|
|
74
|
+
* 处理UniApp特有的事件机制,提取事件处理函数的原始名称
|
|
75
|
+
* @param e 事件对象
|
|
76
|
+
* @returns 处理函数的真实名称
|
|
77
|
+
*/
|
|
78
|
+
private getEventHandlerNameFromE = (e: any): string => {
|
|
79
|
+
let methodName = '__e'; // 默认方法名
|
|
80
|
+
const { type, currentTarget, target } = e;
|
|
81
|
+
const dataSet = currentTarget?.dataset || target?.dataset;
|
|
82
|
+
|
|
83
|
+
// 无数据集时直接返回
|
|
84
|
+
if (!dataSet) {
|
|
85
|
+
return methodName;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 获取事件选项
|
|
89
|
+
const eventOpts = dataSet.eventOpts || dataSet['event-opts'];
|
|
90
|
+
if (!eventOpts) {
|
|
91
|
+
return methodName;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 事件类型匹配函数
|
|
95
|
+
// 处理regionchange等特殊事件类型
|
|
96
|
+
const matchedEventType = (eventType: string, optType: string) =>
|
|
97
|
+
eventType === optType ||
|
|
98
|
+
(optType === 'regionchange' &&
|
|
99
|
+
(eventType === 'begin' || eventType === 'end'));
|
|
100
|
+
|
|
101
|
+
// 遍历事件选项查找匹配的方法名
|
|
102
|
+
eventOpts.forEach((o: any[]) => {
|
|
103
|
+
let eType = ut.head(o); // 获取事件类型
|
|
104
|
+
const isCustom = eType.charAt(0) === CUSTOM;
|
|
105
|
+
eType = isCustom ? eType.slice(1) : type; // 处理自定义事件
|
|
106
|
+
const isOnce = eType.charAt(0) === ONCE;
|
|
107
|
+
eType = isOnce ? eType.slice(1) : type; // 处理一次性事件
|
|
108
|
+
const eArray = ut.last(o); // 获取事件处理数组
|
|
109
|
+
|
|
110
|
+
// 找到匹配的事件类型
|
|
111
|
+
if (matchedEventType(type, eType)) {
|
|
112
|
+
methodName = ut.head(ut.head(eArray)); // 提取方法名
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return methodName;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Vue2专用代理实现
|
|
121
|
+
* 处理Vue2下的特殊情况,主要是生命周期和事件处理
|
|
122
|
+
* Vue2的生命周期有时会异步执行,需要特殊处理
|
|
123
|
+
*/
|
|
124
|
+
uniVue2Proxy = (): void => {
|
|
125
|
+
const {
|
|
126
|
+
dataStore: { eventHooks }
|
|
127
|
+
} = this.growingIO;
|
|
128
|
+
// 重写生命周期回调,vue2中会被处理成异步方法导致时序错位
|
|
129
|
+
this.overrideLifeFcEffectsFn(eventHooks);
|
|
130
|
+
// 初始化原生钩子
|
|
131
|
+
eventHooks.nativeGrowing();
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 重写生命周期效果函数
|
|
136
|
+
* 解决Vue2中页面生命周期异步执行导致的问题
|
|
137
|
+
* 对Page类型的生命周期使用setTimeout延迟执行,保证执行顺序正确
|
|
138
|
+
* @param eventHooks 事件钩子对象
|
|
139
|
+
*/
|
|
140
|
+
private overrideLifeFcEffectsFn = (eventHooks: any): void => {
|
|
141
|
+
const originFunc = eventHooks.lifeFcEffectsFn;
|
|
142
|
+
eventHooks.lifeFcEffectsFn = function (...args) {
|
|
143
|
+
// 对Page类型的生命周期特殊处理
|
|
144
|
+
if (args[2] === 'Page') {
|
|
145
|
+
// 使用setTimeout延迟执行,保证在正确的时机执行
|
|
146
|
+
setTimeout(() => {
|
|
147
|
+
return originFunc.apply(this, args);
|
|
148
|
+
}, 0);
|
|
149
|
+
} else {
|
|
150
|
+
// 非Page类型直接执行原函数
|
|
151
|
+
return originFunc.apply(this, args);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Vue3代理实现
|
|
158
|
+
* 为Vue3框架添加GrowingIO的代理逻辑
|
|
159
|
+
* @param vue Vue3实例
|
|
160
|
+
*/
|
|
161
|
+
uniVue3Proxy = (vue: any): void => {
|
|
79
162
|
const {
|
|
80
163
|
dataStore: { eventHooks },
|
|
81
164
|
minipInstance
|
|
82
165
|
} = this.growingIO;
|
|
166
|
+
|
|
83
167
|
// 重写对象遍历逻辑,优先hook methods最后才是原生
|
|
168
|
+
this.overrideObjectTraverse(eventHooks);
|
|
169
|
+
|
|
170
|
+
// 初始化原生钩子
|
|
171
|
+
eventHooks.nativeGrowing();
|
|
172
|
+
|
|
173
|
+
// 重写getPageTitle方法,确保在Vue组件中能正确获取页面标题
|
|
174
|
+
this.overrideGetPageTitle(minipInstance);
|
|
175
|
+
|
|
176
|
+
// 添加Vue混入,实现组件方法的代理
|
|
177
|
+
this.addVueMixin(vue, eventHooks);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 重写对象遍历逻辑
|
|
182
|
+
* 确保按照正确的优先级遍历对象属性
|
|
183
|
+
* @param eventHooks 事件钩子对象
|
|
184
|
+
*/
|
|
185
|
+
private overrideObjectTraverse = (eventHooks: any): void => {
|
|
84
186
|
eventHooks.objectTraverse = (target: any, fn: any) => {
|
|
187
|
+
// 先处理methods,因为这里包含了大部分自定义方法
|
|
85
188
|
if (ut.has(target, 'methods')) {
|
|
86
189
|
Object.getOwnPropertyNames(target.methods).forEach((k: string) => {
|
|
87
190
|
fn(k, target.methods);
|
|
88
191
|
});
|
|
89
192
|
}
|
|
193
|
+
|
|
194
|
+
// 处理lifetimes,组件生命周期方法
|
|
90
195
|
if (ut.has(target, 'lifetimes')) {
|
|
91
196
|
Object.getOwnPropertyNames(target.lifetimes).forEach((k: string) => {
|
|
92
197
|
fn(k, target.lifetimes);
|
|
93
198
|
});
|
|
94
199
|
}
|
|
200
|
+
|
|
201
|
+
// 处理pageLifetimes,页面生命周期方法
|
|
95
202
|
if (ut.has(target, 'pageLifetimes')) {
|
|
96
203
|
Object.getOwnPropertyNames(target.pageLifetimes).forEach(
|
|
97
204
|
(k: string) => {
|
|
@@ -99,6 +206,8 @@ class GioUniAppAdapter {
|
|
|
99
206
|
}
|
|
100
207
|
);
|
|
101
208
|
}
|
|
209
|
+
|
|
210
|
+
// 最后处理其他属性,确保不重复处理
|
|
102
211
|
Object.getOwnPropertyNames(target).forEach((k: string) => {
|
|
103
212
|
if (
|
|
104
213
|
!ut.niceTry(
|
|
@@ -112,106 +221,208 @@ class GioUniAppAdapter {
|
|
|
112
221
|
}
|
|
113
222
|
});
|
|
114
223
|
};
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* 重写getPageTitle方法
|
|
228
|
+
* 确保能正确获取Vue组件中定义的页面标题
|
|
229
|
+
* @param minipInstance 小程序实例
|
|
230
|
+
*/
|
|
231
|
+
private overrideGetPageTitle = (minipInstance: any): void => {
|
|
232
|
+
const originGetter = minipInstance.getPageTitle; // 保存原始getter
|
|
118
233
|
minipInstance.getPageTitle = function (...args) {
|
|
234
|
+
// 获取当前页面实例
|
|
119
235
|
let pageInstance = !ut.isEmpty(args[0])
|
|
120
236
|
? args[0]
|
|
121
237
|
: minipInstance.getCurrentPage();
|
|
238
|
+
|
|
239
|
+
// 检查是否为页面组件且有路由信息
|
|
122
240
|
if (
|
|
123
241
|
pageInstance?.$vm?.mpType === 'page' &&
|
|
124
242
|
pageInstance?.$vm?.__route__
|
|
125
243
|
) {
|
|
244
|
+
// 优先使用组件中定义的gioPageTitle
|
|
126
245
|
const vmTitle = pageInstance?.$vm?.gioPageTitle;
|
|
127
246
|
return vmTitle ? vmTitle : originGetter.apply(this, args);
|
|
128
247
|
} else {
|
|
248
|
+
// 回退到原始实现
|
|
129
249
|
return originGetter.apply(this, args);
|
|
130
250
|
}
|
|
131
251
|
};
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 添加Vue混入
|
|
256
|
+
* 注入GrowingIO的代理逻辑到Vue组件生命周期中
|
|
257
|
+
* @param vue Vue实例
|
|
258
|
+
* @param eventHooks 事件钩子对象
|
|
259
|
+
*/
|
|
260
|
+
private addVueMixin = (vue: any, eventHooks: any): void => {
|
|
132
261
|
const self = this;
|
|
262
|
+
|
|
133
263
|
vue.mixin({
|
|
264
|
+
// 组件挂载前的钩子
|
|
134
265
|
beforeMount() {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
266
|
+
// 代理普通方法
|
|
267
|
+
self.proxyMethods(this, eventHooks);
|
|
268
|
+
|
|
269
|
+
// 代理exposed方法(script setup中暴露的方法)
|
|
270
|
+
self.proxyExposedMethods(this, eventHooks);
|
|
271
|
+
|
|
272
|
+
// 使用emit监听组件事件hook
|
|
273
|
+
self.proxyEmit(this, eventHooks);
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
// 组件更新时的钩子
|
|
277
|
+
updated() {
|
|
278
|
+
// 更新时重新代理exposed方法,确保动态添加的方法也被代理
|
|
279
|
+
self.proxyExposedMethods(this, eventHooks);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* 代理普通方法
|
|
286
|
+
* 处理传统Vue选项式API和组合式API中定义的方法
|
|
287
|
+
* @param instance Vue组件实例
|
|
288
|
+
* @param eventHooks 事件钩子对象
|
|
289
|
+
*/
|
|
290
|
+
private proxyMethods = (instance: any, eventHooks: any): void => {
|
|
291
|
+
// 代理单个方法的函数
|
|
292
|
+
const proxyMethodFn = (name: string, method: any) => {
|
|
293
|
+
// 只代理非页面生命周期的函数方法
|
|
294
|
+
if (ut.isFunction(method) && !eventHooks.pageHandlers.includes(name)) {
|
|
295
|
+
return function (...args) {
|
|
296
|
+
// 使用customFcEffects包装方法,实现事件追踪
|
|
297
|
+
return eventHooks.customFcEffects(name, method).apply(this, args);
|
|
146
298
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (methods) {
|
|
161
|
-
transferMethods(methods, this);
|
|
162
|
-
}
|
|
163
|
-
// 对setup中定义的事件hook
|
|
164
|
-
const setupState = this?._?.setupState;
|
|
165
|
-
if (setupState) {
|
|
166
|
-
transferMethods(setupState, setupState);
|
|
167
|
-
}
|
|
168
|
-
// 对<script setup>写法的事件hook,编译时会匿名,需要配合expose
|
|
169
|
-
const exposed = this?._?.exposed;
|
|
170
|
-
self.exposedNames = {};
|
|
171
|
-
if (exposed) {
|
|
172
|
-
// 保存exposed供<script setup>写法的事件查找真实的事件名
|
|
173
|
-
const exposedKeys = ut.keys(exposed);
|
|
174
|
-
exposedKeys.forEach((k) => {
|
|
175
|
-
if (ut.isFunction(exposed[k])) {
|
|
176
|
-
self.exposedNames[exposed[k].name] = k;
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
// 只能取到编译后的名称,需要从exposedNames中映射
|
|
180
|
-
const methodKeys = ut
|
|
181
|
-
.keys(this.$scope)
|
|
182
|
-
.filter(
|
|
183
|
-
(k) => UNIAPP_FUNC_REG.test(k) && ut.isFunction(this.$scope[k])
|
|
184
|
-
);
|
|
185
|
-
methodKeys.forEach((k, i) => {
|
|
186
|
-
const originFunc = this.$scope[k].value;
|
|
187
|
-
const customName = self.splicingMethodName(
|
|
188
|
-
originFunc.name,
|
|
189
|
-
k,
|
|
190
|
-
exposedKeys[i]
|
|
191
|
-
);
|
|
192
|
-
this.$scope[k].value = eventHooks.customFcEffects(
|
|
193
|
-
customName,
|
|
194
|
-
originFunc
|
|
195
|
-
);
|
|
299
|
+
} else {
|
|
300
|
+
return method;
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
// 对象属性转移函数,将源对象的方法代理后赋值给目标对象
|
|
305
|
+
const transferMethods = (origin, target) =>
|
|
306
|
+
ut.keys(origin).forEach((k: string) => {
|
|
307
|
+
if (ut.isFunction(target[k])) {
|
|
308
|
+
Object.defineProperty(target, k, {
|
|
309
|
+
value: proxyMethodFn(k, target[k]),
|
|
310
|
+
configurable: true,
|
|
311
|
+
writable: true
|
|
196
312
|
});
|
|
197
313
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// 处理传统选项式API中的methods
|
|
317
|
+
const methods = instance.$options.methods;
|
|
318
|
+
if (methods) {
|
|
319
|
+
transferMethods(methods, instance);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// 处理组合式API中的setup返回值
|
|
323
|
+
const setupState = instance?._?.setupState;
|
|
324
|
+
if (setupState) {
|
|
325
|
+
transferMethods(setupState, setupState);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* 代理exposed方法
|
|
331
|
+
* 处理<script setup>中使用defineExpose暴露的方法
|
|
332
|
+
* @param instance Vue组件实例
|
|
333
|
+
* @param eventHooks 事件钩子对象
|
|
334
|
+
*/
|
|
335
|
+
private proxyExposedMethods = (instance: any, eventHooks: any): void => {
|
|
336
|
+
// 获取组件暴露的方法
|
|
337
|
+
const exposed = instance?._?.exposed;
|
|
338
|
+
this.exposedNames = {}; // 重置映射
|
|
339
|
+
|
|
340
|
+
// 无exposed时直接返回
|
|
341
|
+
if (!exposed) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// 保存exposed供<script setup>写法的事件查找真实的事件名
|
|
346
|
+
const exposedKeys = ut.keys(exposed);
|
|
347
|
+
exposedKeys.forEach((k) => {
|
|
348
|
+
if (ut.isFunction(exposed[k])) {
|
|
349
|
+
// 建立函数名到暴露属性名的映射
|
|
350
|
+
this.exposedNames[exposed[k].name] = k;
|
|
205
351
|
}
|
|
206
352
|
});
|
|
353
|
+
|
|
354
|
+
// 获取编译后的方法列表
|
|
355
|
+
// 使用正则匹配UniApp编译生成的方法名
|
|
356
|
+
const methodKeys = ut
|
|
357
|
+
.keys(instance.$scope)
|
|
358
|
+
.filter(
|
|
359
|
+
(k) => UNIAPP_FUNC_REG.test(k) && ut.isFunction(instance.$scope[k])
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
// 遍历方法进行代理
|
|
363
|
+
methodKeys.forEach((k, i) => {
|
|
364
|
+
const originFunc = instance.$scope[k].value;
|
|
365
|
+
|
|
366
|
+
// 在updated中避免重复hook,通过_GIO_HOOKED_标记判断
|
|
367
|
+
if (instance._.updated && originFunc._GIO_HOOKED_) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// 获取自定义方法名
|
|
372
|
+
const customName = this.splicingMethodName(
|
|
373
|
+
originFunc.name,
|
|
374
|
+
k,
|
|
375
|
+
exposedKeys[i]
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
// 使用customFcEffects包装方法
|
|
379
|
+
instance.$scope[k].value = eventHooks.customFcEffects(
|
|
380
|
+
customName,
|
|
381
|
+
originFunc
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
// 标记已hook过的方法,避免重复处理
|
|
385
|
+
instance.$scope[k].value._GIO_HOOKED_ = true;
|
|
386
|
+
});
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* 代理emit方法
|
|
391
|
+
* 监听组件通过emit触发的事件
|
|
392
|
+
* @param instance Vue组件实例
|
|
393
|
+
* @param eventHooks 事件钩子对象
|
|
394
|
+
*/
|
|
395
|
+
private proxyEmit = (instance: any, eventHooks: any): void => {
|
|
396
|
+
const tEmit = instance._.emit; // 保存原始emit方法
|
|
397
|
+
instance._.emit = function (...args) {
|
|
398
|
+
// 使用自执行函数触发事件追踪,传入空函数作为handler
|
|
399
|
+
(() => eventHooks.customFcEffects(args[0], () => {}).apply(this, args))();
|
|
400
|
+
// 调用原始emit方法
|
|
401
|
+
return tEmit.apply(this, args);
|
|
402
|
+
};
|
|
207
403
|
};
|
|
208
404
|
|
|
209
|
-
|
|
405
|
+
/**
|
|
406
|
+
* 拼接方法名称
|
|
407
|
+
* 根据不同情况组合出最终的方法名
|
|
408
|
+
* @param originName 原始名称
|
|
409
|
+
* @param traversalName 遍历得到的名称
|
|
410
|
+
* @param exposedName 暴露的名称
|
|
411
|
+
* @returns 最终使用的方法名
|
|
412
|
+
*/
|
|
413
|
+
splicingMethodName = (
|
|
414
|
+
originName: string,
|
|
415
|
+
traversalName: string,
|
|
416
|
+
exposedName: string
|
|
417
|
+
): string => {
|
|
210
418
|
if (originName) {
|
|
419
|
+
// 优先使用原始名称
|
|
211
420
|
return originName;
|
|
212
421
|
} else if (exposedName) {
|
|
422
|
+
// 其次使用遍历名称和暴露名称的组合
|
|
213
423
|
return `${traversalName}#${exposedName}`;
|
|
214
424
|
} else {
|
|
425
|
+
// 最后使用遍历名称
|
|
215
426
|
return traversalName;
|
|
216
427
|
}
|
|
217
428
|
};
|
package/src/constants/emitMsg.ts
CHANGED
|
@@ -9,6 +9,7 @@ export default {
|
|
|
9
9
|
ON_SDK_INITIALIZE_BEFORE: 'ON_SDK_INITIALIZE_BEFORE', // SDK开始初始化之前
|
|
10
10
|
ON_SEND_AFTER: 'ON_SEND_AFTER', // 插件生命周期:发送事件后
|
|
11
11
|
ON_SEND_BEFORE: 'ON_SEND_BEFORE', // 插件生命周期:发送事件前
|
|
12
|
+
ON_SEND_ERROR: 'ON_SEND_ERROR', // 插件生命周期:发送事件错误
|
|
12
13
|
OPTION_CHANGE: 'OPTION_CHANGE', // 设置变更事件
|
|
13
14
|
OPTION_INITIALIZED: 'OPTION_INITIALIZED', // 配置项初始化完成
|
|
14
15
|
SCENE_UPDATE: 'SCENE_UPDATE', // scene变更事件
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AppHookLifeCircle } from '@@/types/eventHooks';
|
|
2
2
|
import { GrowingIOType } from '@@/types/growingIO';
|
|
3
|
-
import { isEmpty, typeOf } from '@@/utils/glodash';
|
|
3
|
+
import { isEmpty, typeOf, unset } from '@@/utils/glodash';
|
|
4
4
|
import { getLaunchQuery, qsStringify } from '@@/utils/tools';
|
|
5
5
|
import EMIT_MSG from '@@/constants/emitMsg';
|
|
6
6
|
|
|
@@ -17,6 +17,7 @@ class AppEffects {
|
|
|
17
17
|
platformConfig,
|
|
18
18
|
uploader,
|
|
19
19
|
dataStore,
|
|
20
|
+
minipInstance,
|
|
20
21
|
dataStore: {
|
|
21
22
|
trackersExecute,
|
|
22
23
|
shareOut,
|
|
@@ -81,6 +82,8 @@ class AppEffects {
|
|
|
81
82
|
userStore.setSessionId(trackingId);
|
|
82
83
|
});
|
|
83
84
|
}
|
|
85
|
+
// 添加网络状态变更监听
|
|
86
|
+
minipInstance.setNetworkStatusListener();
|
|
84
87
|
break;
|
|
85
88
|
}
|
|
86
89
|
case appListeners.appClose: {
|
|
@@ -121,6 +124,8 @@ class AppEffects {
|
|
|
121
124
|
rQuery = query || args.query;
|
|
122
125
|
rAppId = referrerInfo?.appId || args?.referrerInfo?.appId || '';
|
|
123
126
|
dataStore.scene = scene || args.scene;
|
|
127
|
+
// 移除某些小程序圈选时我们带入的圈选地址参数
|
|
128
|
+
unset(query, 'gdpCircleRoomCollectUrl');
|
|
124
129
|
// 来源有额外参数时并入页面参数
|
|
125
130
|
if (!isEmpty(referrerInfo?.extraData)) {
|
|
126
131
|
rQuery = qsStringify(getLaunchQuery(rQuery, referrerInfo.extraData));
|