mp-weixin-back 0.0.11 → 0.0.13

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/client.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  declare module 'mp-weixin-back-helper' {
2
2
  type Config = {
3
- /**
3
+ /**
4
+ * 初始化时是否监听手势返回,默认值为`true`
5
+ */
6
+ initialValue: boolean
7
+ /**
4
8
  * 是否阻止默认的回退事件,默认为 false
5
9
  */
6
10
  preventDefault: boolean
@@ -10,10 +14,19 @@ declare module 'mp-weixin-back-helper' {
10
14
  frequency: number
11
15
  }
12
16
 
13
- function onPageBack(
14
- callback:() => void,
15
- params: Partial<Config>
16
- )
17
+ function onPageBack(callback: () => void, params?: Partial<Config>)
18
+
19
+ /**
20
+ * 开启监听手势滑动事件
21
+ */
22
+ function activeMpBack()
23
+
24
+ /**
25
+ * 禁用监听手势滑动事件
26
+ */
27
+ function inactiveMpBack()
17
28
 
18
29
  export default onPageBack
19
- }
30
+
31
+ export { activeMpBack, inactiveMpBack }
32
+ }
package/dist/index.cjs CHANGED
@@ -33,16 +33,33 @@ function compositionWalk(context, code, sfc, id) {
33
33
  pageBackFnName: "onPageBack",
34
34
  hasImportRef: false,
35
35
  backConfig: { ...context.config },
36
- callbackCode: ""
36
+ onPageBackBodyAst: [],
37
+ onPageBackCallNodeToRemove: null,
38
+ activeFnName: "activeMpBack",
39
+ inActiveFnName: "inactiveMpBack"
37
40
  };
41
+ const activeFnCallsToModify = [];
42
+ const inActiveFnCallsToModify = [];
38
43
  if (setupAst) {
39
44
  astKit.walkAST(setupAst, {
40
45
  enter(node) {
41
46
  if (node.type === "ImportDeclaration") {
42
47
  if (node.source.value.includes(virtualFileId)) {
43
- const importSpecifier = node.specifiers[0];
48
+ const importDefaultSpecifiers = node.specifiers.filter(
49
+ (i) => i.type === "ImportDefaultSpecifier"
50
+ );
51
+ const importDefaultSpecifier = importDefaultSpecifiers[0];
44
52
  pageInfo.hasPageBack = true;
45
- pageInfo.pageBackFnName = importSpecifier.local.name;
53
+ pageInfo.pageBackFnName = importDefaultSpecifier.local.name;
54
+ const importSpecifiers = node.specifiers.filter((i) => i.type === "ImportSpecifier");
55
+ importSpecifiers.map((specifiers) => {
56
+ if (specifiers.imported.type === "Identifier" && specifiers.imported.name === "activeMpBack") {
57
+ pageInfo.activeFnName = specifiers.local.name;
58
+ }
59
+ if (specifiers.imported.type === "Identifier" && specifiers.imported.name === "inactiveMpBack") {
60
+ pageInfo.inActiveFnName = specifiers.local.name;
61
+ }
62
+ });
46
63
  }
47
64
  if (node.source.value === "vue") {
48
65
  node.specifiers.some((specifier) => {
@@ -55,6 +72,7 @@ function compositionWalk(context, code, sfc, id) {
55
72
  }
56
73
  }
57
74
  if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageInfo.pageBackFnName) {
75
+ pageInfo.onPageBackCallNodeToRemove = node;
58
76
  const callback = node.expression.arguments[0];
59
77
  const backArguments = node.expression.arguments[1];
60
78
  if (backArguments?.type === "ObjectExpression") {
@@ -65,30 +83,77 @@ function compositionWalk(context, code, sfc, id) {
65
83
  Object.assign(pageInfo.backConfig, config);
66
84
  }
67
85
  if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
68
- const body = callback.body;
69
- if (body.type === "BlockStatement") {
70
- pageInfo.callbackCode += body.body.map(
71
- // @ts-ignore
72
- (statement) => (generate__default.default ? generate__default.default : generate__default)(statement).code
73
- ).join("");
74
- }
86
+ pageInfo.onPageBackBodyAst = callback.body.body;
75
87
  }
88
+ return;
89
+ }
90
+ if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageInfo.activeFnName) {
91
+ activeFnCallsToModify.push({
92
+ start: node.expression.start,
93
+ end: node.expression.end,
94
+ original: sfc.scriptSetup.loc.source.substring(
95
+ node.expression.start,
96
+ node.expression.end
97
+ ),
98
+ name: pageInfo.activeFnName
99
+ });
100
+ }
101
+ if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageInfo.inActiveFnName) {
102
+ inActiveFnCallsToModify.push({
103
+ start: node.expression.start,
104
+ end: node.expression.end,
105
+ original: sfc.scriptSetup.loc.source.substring(
106
+ node.expression.start,
107
+ node.expression.end
108
+ ),
109
+ name: pageInfo.inActiveFnName
110
+ });
76
111
  }
77
112
  }
78
113
  });
79
114
  }
80
115
  if (!pageInfo.hasPageBack)
81
116
  return code;
117
+ if (pageInfo.onPageBackCallNodeToRemove) {
118
+ const scriptSetupOffset = sfc.scriptSetup.loc.start.offset;
119
+ const nodeToRemove = pageInfo.onPageBackCallNodeToRemove;
120
+ const globalStart = scriptSetupOffset + nodeToRemove.start;
121
+ const globalEnd = scriptSetupOffset + nodeToRemove.end;
122
+ codeMs.remove(globalStart, globalEnd);
123
+ }
124
+ let callbackCode = "";
125
+ if (pageInfo.onPageBackBodyAst.length > 0) {
126
+ const tempAstRoot = {
127
+ type: "BlockStatement",
128
+ body: pageInfo.onPageBackBodyAst
129
+ };
130
+ astKit.walkAST(tempAstRoot, {
131
+ enter(node) {
132
+ if (node.type === "CallExpression" && node.callee.type === "Identifier") {
133
+ const createIdentifier = (name) => ({ type: "Identifier", name });
134
+ if (node.callee.name === pageInfo.activeFnName) {
135
+ node.arguments.unshift(createIdentifier("__MP_WEIXIN_ACTIVEBACK__"));
136
+ } else if (node.callee.name === pageInfo.inActiveFnName) {
137
+ node.arguments.unshift(createIdentifier("__MP_WEIXIN_INACTIVEBACK__"));
138
+ }
139
+ }
140
+ }
141
+ });
142
+ callbackCode = pageInfo.onPageBackBodyAst.map((statement) => (generate__default.default ? generate__default.default : generate__default)(statement).code).join("\n");
143
+ }
82
144
  if (code.includes("<page-container")) {
83
145
  context.log.debugLog(`${context.getPageById(id)}\u9875\u9762\u5DF2\u6709page-container\u7EC4\u4EF6\uFF0C\u6CE8\u5165\u5931\u8D25`);
84
146
  return code;
85
147
  }
86
148
  if (!pageInfo.backConfig.preventDefault) {
87
- pageInfo.callbackCode += "uni.navigateBack({ delta: 1 });";
149
+ callbackCode += "uni.navigateBack({ delta: 1 });";
88
150
  }
151
+ const importUseMpWeixinBack = `import { useMpWeixinBack } from '${virtualFileId}'`;
89
152
  const importRefFromVue = !pageInfo.hasImportRef ? `import { ref } from 'vue'` : "";
90
153
  const stateFrequency = "let __MP_BACK_FREQUENCY__ = 1;";
91
- const statePageContainerVar = "const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(true);";
154
+ const statePageContainerVar = `
155
+ const { __MP_BACK_SHOW_PAGE_CONTAINER__, __MP_WEIXIN_ACTIVEBACK__, __MP_WEIXIN_INACTIVEBACK__ } = useMpWeixinBack(${pageInfo.backConfig.initialValue})
156
+ `;
92
157
  const configBack = (() => {
93
158
  const onPageBack = pageInfo.backConfig.onPageBack;
94
159
  if (!onPageBack)
@@ -104,13 +169,16 @@ function compositionWalk(context, code, sfc, id) {
104
169
  })();
105
170
  const stateBeforeLeave = `
106
171
  const onBeforeLeave = () => {
172
+ if (!__MP_BACK_SHOW_PAGE_CONTAINER__.value) {
173
+ return
174
+ }
107
175
  if (__MP_BACK_FREQUENCY__ < ${pageInfo.backConfig.frequency}) {
108
176
  __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
109
177
  setTimeout(() => __MP_BACK_SHOW_PAGE_CONTAINER__.value = true, 0);
110
178
  __MP_BACK_FREQUENCY__++
111
179
  }
112
180
  ${configBack}
113
- ${pageInfo.callbackCode}
181
+ ${callbackCode}
114
182
  };
115
183
  `;
116
184
  const { template, scriptSetup } = sfc;
@@ -130,10 +198,31 @@ function compositionWalk(context, code, sfc, id) {
130
198
  const scriptMagicString = new MagicString__default(scriptOffsets.content);
131
199
  scriptMagicString.prepend(
132
200
  ` ${importRefFromVue}
201
+ ${importUseMpWeixinBack}
133
202
  ${stateFrequency}
134
203
  ${statePageContainerVar}
135
204
  ${stateBeforeLeave} `
136
205
  );
206
+ activeFnCallsToModify.forEach((call) => {
207
+ const fnCallRegex = new RegExp(`${call.name}\\(([^)]*)\\)`, "g");
208
+ const newCall = call.original.replace(fnCallRegex, (_match, args) => {
209
+ if (!args.trim()) {
210
+ return `${call.name}(__MP_WEIXIN_ACTIVEBACK__)`;
211
+ }
212
+ return `${call.name}(__MP_WEIXIN_ACTIVEBACK__, ${args})`;
213
+ });
214
+ scriptMagicString.overwrite(call.start, call.end, newCall);
215
+ });
216
+ inActiveFnCallsToModify.forEach((call) => {
217
+ const fnCallRegex = new RegExp(`${call.name}\\(([^)]*)\\)`, "g");
218
+ const newCall = call.original.replace(fnCallRegex, (_match, args) => {
219
+ if (!args.trim()) {
220
+ return `${call.name}(__MP_WEIXIN_INACTIVEBACK__)`;
221
+ }
222
+ return `${call.name}(__MP_WEIXIN_INACTIVEBACK__, ${args})`;
223
+ });
224
+ scriptMagicString.overwrite(call.start, call.end, newCall);
225
+ });
137
226
  codeMs.overwrite(scriptOffsets.start, scriptOffsets.end, scriptMagicString.toString());
138
227
  return codeMs.toString();
139
228
  }
@@ -413,6 +502,7 @@ class pageContext {
413
502
  function MpBackPlugin(userOptions = {}) {
414
503
  let context;
415
504
  const defaultOptions = {
505
+ initialValue: true,
416
506
  preventDefault: false,
417
507
  frequency: 1,
418
508
  debug: false
@@ -437,7 +527,33 @@ function MpBackPlugin(userOptions = {}) {
437
527
  return;
438
528
  }
439
529
  if (id === virtualFileId) {
440
- return `export default function onPageBack() {}`;
530
+ return `
531
+ import { ref } from 'vue'
532
+ export default function onPageBack() {}
533
+ export function activeMpBack(fn = null) {
534
+ fn?.()
535
+ }
536
+ export function inactiveMpBack(fn = null) {
537
+ fn?.()
538
+ }
539
+ export function useMpWeixinBack(initialValue = true) {
540
+ const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(initialValue)
541
+
542
+ const __MP_WEIXIN_ACTIVEBACK__ = () => {
543
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = true
544
+ }
545
+
546
+ const __MP_WEIXIN_INACTIVEBACK__ = () => {
547
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
548
+ }
549
+
550
+ return {
551
+ __MP_BACK_SHOW_PAGE_CONTAINER__,
552
+ __MP_WEIXIN_ACTIVEBACK__,
553
+ __MP_WEIXIN_INACTIVEBACK__
554
+ }
555
+ }
556
+ `;
441
557
  }
442
558
  },
443
559
  async transform(code, id) {
package/dist/index.d.cts CHANGED
@@ -2,6 +2,10 @@ import { Plugin } from 'vite';
2
2
 
3
3
  type UserOptions = Partial<Config>;
4
4
  type Config = {
5
+ /**
6
+ * 初始化时是否监听手势返回,默认值为`true`
7
+ */
8
+ initialValue: boolean;
5
9
  /**
6
10
  * 是否阻止默认的回退事件,默认为 false
7
11
  */
package/dist/index.d.mts CHANGED
@@ -2,6 +2,10 @@ import { Plugin } from 'vite';
2
2
 
3
3
  type UserOptions = Partial<Config>;
4
4
  type Config = {
5
+ /**
6
+ * 初始化时是否监听手势返回,默认值为`true`
7
+ */
8
+ initialValue: boolean;
5
9
  /**
6
10
  * 是否阻止默认的回退事件,默认为 false
7
11
  */
package/dist/index.d.ts CHANGED
@@ -2,6 +2,10 @@ import { Plugin } from 'vite';
2
2
 
3
3
  type UserOptions = Partial<Config>;
4
4
  type Config = {
5
+ /**
6
+ * 初始化时是否监听手势返回,默认值为`true`
7
+ */
8
+ initialValue: boolean;
5
9
  /**
6
10
  * 是否阻止默认的回退事件,默认为 false
7
11
  */
package/dist/index.mjs CHANGED
@@ -23,16 +23,33 @@ function compositionWalk(context, code, sfc, id) {
23
23
  pageBackFnName: "onPageBack",
24
24
  hasImportRef: false,
25
25
  backConfig: { ...context.config },
26
- callbackCode: ""
26
+ onPageBackBodyAst: [],
27
+ onPageBackCallNodeToRemove: null,
28
+ activeFnName: "activeMpBack",
29
+ inActiveFnName: "inactiveMpBack"
27
30
  };
31
+ const activeFnCallsToModify = [];
32
+ const inActiveFnCallsToModify = [];
28
33
  if (setupAst) {
29
34
  walkAST(setupAst, {
30
35
  enter(node) {
31
36
  if (node.type === "ImportDeclaration") {
32
37
  if (node.source.value.includes(virtualFileId)) {
33
- const importSpecifier = node.specifiers[0];
38
+ const importDefaultSpecifiers = node.specifiers.filter(
39
+ (i) => i.type === "ImportDefaultSpecifier"
40
+ );
41
+ const importDefaultSpecifier = importDefaultSpecifiers[0];
34
42
  pageInfo.hasPageBack = true;
35
- pageInfo.pageBackFnName = importSpecifier.local.name;
43
+ pageInfo.pageBackFnName = importDefaultSpecifier.local.name;
44
+ const importSpecifiers = node.specifiers.filter((i) => i.type === "ImportSpecifier");
45
+ importSpecifiers.map((specifiers) => {
46
+ if (specifiers.imported.type === "Identifier" && specifiers.imported.name === "activeMpBack") {
47
+ pageInfo.activeFnName = specifiers.local.name;
48
+ }
49
+ if (specifiers.imported.type === "Identifier" && specifiers.imported.name === "inactiveMpBack") {
50
+ pageInfo.inActiveFnName = specifiers.local.name;
51
+ }
52
+ });
36
53
  }
37
54
  if (node.source.value === "vue") {
38
55
  node.specifiers.some((specifier) => {
@@ -45,6 +62,7 @@ function compositionWalk(context, code, sfc, id) {
45
62
  }
46
63
  }
47
64
  if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageInfo.pageBackFnName) {
65
+ pageInfo.onPageBackCallNodeToRemove = node;
48
66
  const callback = node.expression.arguments[0];
49
67
  const backArguments = node.expression.arguments[1];
50
68
  if (backArguments?.type === "ObjectExpression") {
@@ -55,30 +73,77 @@ function compositionWalk(context, code, sfc, id) {
55
73
  Object.assign(pageInfo.backConfig, config);
56
74
  }
57
75
  if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
58
- const body = callback.body;
59
- if (body.type === "BlockStatement") {
60
- pageInfo.callbackCode += body.body.map(
61
- // @ts-ignore
62
- (statement) => (generate.default ? generate.default : generate)(statement).code
63
- ).join("");
64
- }
76
+ pageInfo.onPageBackBodyAst = callback.body.body;
65
77
  }
78
+ return;
79
+ }
80
+ if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageInfo.activeFnName) {
81
+ activeFnCallsToModify.push({
82
+ start: node.expression.start,
83
+ end: node.expression.end,
84
+ original: sfc.scriptSetup.loc.source.substring(
85
+ node.expression.start,
86
+ node.expression.end
87
+ ),
88
+ name: pageInfo.activeFnName
89
+ });
90
+ }
91
+ if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageInfo.inActiveFnName) {
92
+ inActiveFnCallsToModify.push({
93
+ start: node.expression.start,
94
+ end: node.expression.end,
95
+ original: sfc.scriptSetup.loc.source.substring(
96
+ node.expression.start,
97
+ node.expression.end
98
+ ),
99
+ name: pageInfo.inActiveFnName
100
+ });
66
101
  }
67
102
  }
68
103
  });
69
104
  }
70
105
  if (!pageInfo.hasPageBack)
71
106
  return code;
107
+ if (pageInfo.onPageBackCallNodeToRemove) {
108
+ const scriptSetupOffset = sfc.scriptSetup.loc.start.offset;
109
+ const nodeToRemove = pageInfo.onPageBackCallNodeToRemove;
110
+ const globalStart = scriptSetupOffset + nodeToRemove.start;
111
+ const globalEnd = scriptSetupOffset + nodeToRemove.end;
112
+ codeMs.remove(globalStart, globalEnd);
113
+ }
114
+ let callbackCode = "";
115
+ if (pageInfo.onPageBackBodyAst.length > 0) {
116
+ const tempAstRoot = {
117
+ type: "BlockStatement",
118
+ body: pageInfo.onPageBackBodyAst
119
+ };
120
+ walkAST(tempAstRoot, {
121
+ enter(node) {
122
+ if (node.type === "CallExpression" && node.callee.type === "Identifier") {
123
+ const createIdentifier = (name) => ({ type: "Identifier", name });
124
+ if (node.callee.name === pageInfo.activeFnName) {
125
+ node.arguments.unshift(createIdentifier("__MP_WEIXIN_ACTIVEBACK__"));
126
+ } else if (node.callee.name === pageInfo.inActiveFnName) {
127
+ node.arguments.unshift(createIdentifier("__MP_WEIXIN_INACTIVEBACK__"));
128
+ }
129
+ }
130
+ }
131
+ });
132
+ callbackCode = pageInfo.onPageBackBodyAst.map((statement) => (generate.default ? generate.default : generate)(statement).code).join("\n");
133
+ }
72
134
  if (code.includes("<page-container")) {
73
135
  context.log.debugLog(`${context.getPageById(id)}\u9875\u9762\u5DF2\u6709page-container\u7EC4\u4EF6\uFF0C\u6CE8\u5165\u5931\u8D25`);
74
136
  return code;
75
137
  }
76
138
  if (!pageInfo.backConfig.preventDefault) {
77
- pageInfo.callbackCode += "uni.navigateBack({ delta: 1 });";
139
+ callbackCode += "uni.navigateBack({ delta: 1 });";
78
140
  }
141
+ const importUseMpWeixinBack = `import { useMpWeixinBack } from '${virtualFileId}'`;
79
142
  const importRefFromVue = !pageInfo.hasImportRef ? `import { ref } from 'vue'` : "";
80
143
  const stateFrequency = "let __MP_BACK_FREQUENCY__ = 1;";
81
- const statePageContainerVar = "const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(true);";
144
+ const statePageContainerVar = `
145
+ const { __MP_BACK_SHOW_PAGE_CONTAINER__, __MP_WEIXIN_ACTIVEBACK__, __MP_WEIXIN_INACTIVEBACK__ } = useMpWeixinBack(${pageInfo.backConfig.initialValue})
146
+ `;
82
147
  const configBack = (() => {
83
148
  const onPageBack = pageInfo.backConfig.onPageBack;
84
149
  if (!onPageBack)
@@ -94,13 +159,16 @@ function compositionWalk(context, code, sfc, id) {
94
159
  })();
95
160
  const stateBeforeLeave = `
96
161
  const onBeforeLeave = () => {
162
+ if (!__MP_BACK_SHOW_PAGE_CONTAINER__.value) {
163
+ return
164
+ }
97
165
  if (__MP_BACK_FREQUENCY__ < ${pageInfo.backConfig.frequency}) {
98
166
  __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
99
167
  setTimeout(() => __MP_BACK_SHOW_PAGE_CONTAINER__.value = true, 0);
100
168
  __MP_BACK_FREQUENCY__++
101
169
  }
102
170
  ${configBack}
103
- ${pageInfo.callbackCode}
171
+ ${callbackCode}
104
172
  };
105
173
  `;
106
174
  const { template, scriptSetup } = sfc;
@@ -120,10 +188,31 @@ function compositionWalk(context, code, sfc, id) {
120
188
  const scriptMagicString = new MagicString(scriptOffsets.content);
121
189
  scriptMagicString.prepend(
122
190
  ` ${importRefFromVue}
191
+ ${importUseMpWeixinBack}
123
192
  ${stateFrequency}
124
193
  ${statePageContainerVar}
125
194
  ${stateBeforeLeave} `
126
195
  );
196
+ activeFnCallsToModify.forEach((call) => {
197
+ const fnCallRegex = new RegExp(`${call.name}\\(([^)]*)\\)`, "g");
198
+ const newCall = call.original.replace(fnCallRegex, (_match, args) => {
199
+ if (!args.trim()) {
200
+ return `${call.name}(__MP_WEIXIN_ACTIVEBACK__)`;
201
+ }
202
+ return `${call.name}(__MP_WEIXIN_ACTIVEBACK__, ${args})`;
203
+ });
204
+ scriptMagicString.overwrite(call.start, call.end, newCall);
205
+ });
206
+ inActiveFnCallsToModify.forEach((call) => {
207
+ const fnCallRegex = new RegExp(`${call.name}\\(([^)]*)\\)`, "g");
208
+ const newCall = call.original.replace(fnCallRegex, (_match, args) => {
209
+ if (!args.trim()) {
210
+ return `${call.name}(__MP_WEIXIN_INACTIVEBACK__)`;
211
+ }
212
+ return `${call.name}(__MP_WEIXIN_INACTIVEBACK__, ${args})`;
213
+ });
214
+ scriptMagicString.overwrite(call.start, call.end, newCall);
215
+ });
127
216
  codeMs.overwrite(scriptOffsets.start, scriptOffsets.end, scriptMagicString.toString());
128
217
  return codeMs.toString();
129
218
  }
@@ -403,6 +492,7 @@ class pageContext {
403
492
  function MpBackPlugin(userOptions = {}) {
404
493
  let context;
405
494
  const defaultOptions = {
495
+ initialValue: true,
406
496
  preventDefault: false,
407
497
  frequency: 1,
408
498
  debug: false
@@ -427,7 +517,33 @@ function MpBackPlugin(userOptions = {}) {
427
517
  return;
428
518
  }
429
519
  if (id === virtualFileId) {
430
- return `export default function onPageBack() {}`;
520
+ return `
521
+ import { ref } from 'vue'
522
+ export default function onPageBack() {}
523
+ export function activeMpBack(fn = null) {
524
+ fn?.()
525
+ }
526
+ export function inactiveMpBack(fn = null) {
527
+ fn?.()
528
+ }
529
+ export function useMpWeixinBack(initialValue = true) {
530
+ const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(initialValue)
531
+
532
+ const __MP_WEIXIN_ACTIVEBACK__ = () => {
533
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = true
534
+ }
535
+
536
+ const __MP_WEIXIN_INACTIVEBACK__ = () => {
537
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
538
+ }
539
+
540
+ return {
541
+ __MP_BACK_SHOW_PAGE_CONTAINER__,
542
+ __MP_WEIXIN_ACTIVEBACK__,
543
+ __MP_WEIXIN_INACTIVEBACK__
544
+ }
545
+ }
546
+ `;
431
547
  }
432
548
  },
433
549
  async transform(code, id) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mp-weixin-back",
3
3
  "type": "module",
4
- "version": "0.0.11",
4
+ "version": "0.0.13",
5
5
  "description": "监听微信小程序的手势返回和页面默认导航栏的返回",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
package/readme.md CHANGED
@@ -1,82 +1,151 @@
1
- ### 功能描述
1
+ # mp-weixin-back
2
2
 
3
- 监听手势返回和页面默认导航栏的返回事件
3
+ ## 功能概述
4
4
 
5
- ### 在项目中使用
5
+ `mp-weixin-back` 是一个专门用于监听微信小程序`手势返回`、`导航栏返回事件`、`navigateBack`的工具库,提供灵活的配置选项和简洁的 API。
6
6
 
7
- #### 下载
7
+ ## 📦 安装
8
8
 
9
- ```ts
9
+ ```bash
10
10
  npm install mp-weixin-back
11
+ # 或
12
+ yarn add mp-weixin-back
11
13
  ```
12
14
 
13
- #### 使用
15
+ ## ⚙️ Vite 配置
14
16
 
15
- `vite.config.ts` 中配置
17
+ `vite.config.ts` 中添加插件:
16
18
 
17
19
  ```ts
20
+ import { defineConfig } from 'vite'
18
21
  import mpBackPlugin from 'mp-weixin-back'
19
22
 
20
23
  export default defineConfig({
21
- plugins: [mpBackPlugin()],
24
+ plugins: [
25
+ mpBackPlugin({
26
+ // 可选配置项
27
+ preventDefault: false, // 是否阻止默认返回行为,设置成 true 则不会返回上一层
28
+ frequency: 1, // 阻止次数,需要一直拦截则设置一个很大的值即可,如:9999
29
+ debug: false, // 调试模式,默认为 false
30
+ onPageBack: () => {
31
+ console.log('返回事件触发')
32
+ }, // 统一钩子,事件触发时执行
33
+ }),
34
+ ],
22
35
  })
23
36
  ```
24
37
 
25
- 具体的配置为:
26
-
27
- ```ts
28
- type Config = {
29
- /**
30
- * 是否阻止默认的回退事件,默认为 false
31
- */
32
- preventDefault: boolean
33
- /**
34
- * 阻止次数,默认是 `1`
35
- */
36
- frequency: number
37
- /**
38
- * 页面回退时触发
39
- */
40
- onPageBack?: (params: BackParams) => void
41
- }
42
- ```
38
+ ## 🚀 快速开始
43
39
 
44
- vue3 中使用
40
+ ### 基本使用
45
41
 
46
42
  ```ts
43
+ <script setup>
47
44
  import onPageBack from 'mp-weixin-back-helper'
48
45
 
46
+ // 简单监听返回事件
49
47
  onPageBack(() => {
50
- console.log('触发了手势返回')
48
+ console.log('检测到返回操作(手势或导航栏返回)')
49
+ // 在这里添加你的处理逻辑
51
50
  })
51
+ </script>
52
52
  ```
53
53
 
54
- onPageBack 的类型定义为:
54
+ ### 高级配置
55
55
 
56
56
  ```ts
57
- type Config = {
58
- /**
59
- * 是否阻止默认的回退事件,默认为 false
60
- */
61
- preventDefault: boolean
62
- /**
63
- * 阻止次数,默认是 `1`
64
- */
65
- frequency: number
66
- }
67
-
68
- function onPageBack(callback: () => void, params: Partial<Config>)
57
+ // 带配置的监听
58
+ onPageBack(
59
+ () => {
60
+ console.log('返回事件被触发')
61
+ // 自定义处理逻辑
62
+ },
63
+ {
64
+ initialValue: false, // 立即生效,默认值为`true`
65
+ preventDefault: true, // 阻止默认返回行为
66
+ frequency: 2, // 阻止次数为2次
67
+ }
68
+ )
69
69
  ```
70
70
 
71
- #### 引入类型
71
+ ## 📚 API 文档
72
+
73
+ ### `onPageBack(callback, config?)`
74
+
75
+ 监听页面返回事件
76
+
77
+ | 参数 | 类型 | 必填 | 说明 |
78
+ | -------- | ------------ | ---- | ------------------------ |
79
+ | callback | `() => void` | 是 | 返回事件触发时的回调函数 |
80
+ | options | Object | 否 | 监听器配置选项 |
81
+
82
+ #### 配置选项
83
+
84
+ | 参数 | 类型 | 默认值 | 说明 |
85
+ | -------------- | ------- | ------ | ----------------------------------------------- |
86
+ | preventDefault | boolean | false | 是否阻止默认返回行为(true 时页面不会实际返回) |
87
+ | frequency | number | 1 | 阻止次数 |
88
+ | initialValue | boolean | true | 是否立即启用监听(设为 false 时需手动激活) |
89
+
90
+ ### 辅助方法
91
+
92
+ #### `activeMpBack()`
93
+
94
+ 启用返回事件监听(需在`<script setup>`中执行)
95
+
96
+ #### `inactiveMpBack()`
97
+
98
+ 禁用返回事件监听(需在`<script setup>`中执行)
99
+
100
+ 举例:
72
101
 
73
- 在项目目录中的`src/env.d.ts` 或`src/shime-uni.d.ts` 文件中引入
102
+ ```html
103
+ <template>
104
+ <div>
105
+ <!-- 页面代码 -->
106
+ <button @click="toggleListener(true)">开启</button>
107
+ <button @click="toggleListener(false)">禁用</button>
108
+ </div>
109
+ </template>
74
110
 
111
+ <script setup>
112
+ import onPageBack, { activeMpBack, inactiveMpBack } from 'mp-weixin-back-helper'
113
+
114
+ const toggleListener = (enable) => {
115
+ enable ? activeMpBack() : inactiveMpBack()
116
+ }
117
+ </script>
75
118
  ```
76
- /// <reference types="mp-weixin-back/client" />
119
+
120
+ ## 🎯 选项式 API 支持(未完善)
121
+
122
+ 组件内直接声明
123
+
124
+ 在 Vue 组件的选项对象中直接定义 onPageBack 方法:
125
+
126
+ ```html
127
+ <template>
128
+ <div class="container">
129
+ <div>当前页面内容</div>
130
+ </div>
131
+ </template>
132
+
133
+ <script>
134
+ export default {
135
+ // 读取 vite 中的配置
136
+ onPageBack() {
137
+ console.log('检测到返回操作')
138
+ // 业务逻辑处理
139
+ },
140
+ }
141
+ </script>
77
142
  ```
78
143
 
79
- 或在 `tsconfig.json` 的 `compilerOptions` 下配置
144
+ ## 🛠 类型支持
145
+
146
+ ### 类型声明配置
147
+
148
+ 在 `tsconfig.json` 中添加:
80
149
 
81
150
  ```json
82
151
  {
@@ -86,9 +155,19 @@ function onPageBack(callback: () => void, params: Partial<Config>)
86
155
  }
87
156
  ```
88
157
 
89
- ### todolist
158
+ 或通过声明文件引用:
159
+
160
+ ```typescript
161
+ // env.d.ts
162
+ /// <reference types="mp-weixin-back/client" />
163
+ ```
164
+
165
+ ## ❓ 常见问题
166
+
167
+ ### Q1: 如何实现多页面独立配置?
168
+
169
+ 每个页面单独调用 `onPageBack` 时传入不同的配置参数即可实现页面级定制。
170
+
171
+ ### Q2: 全局配置与页面配置的优先级?
90
172
 
91
- - [ ] 兼容 uniapp 的 Vue2 项目
92
- - [ ] debug 模式
93
- - [ ] 热更新 pages.json 文件
94
- - [ ] 单元测试
173
+ 页面级配置会覆盖全局配置,建议将通用配置放在全局,特殊需求在页面单独设置。
package/shims-vue.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ // shims-vue.d.ts
2
+ declare module '*.vue' {
3
+ import { DefineComponent } from 'vue'
4
+ const component: DefineComponent<{}, {}, any>
5
+ export default component
6
+ }
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ function MpBackPlugin(userOptions: UserOptions = {}): Plugin {
7
7
  let context: pageContext
8
8
 
9
9
  const defaultOptions: Config = {
10
+ initialValue: true,
10
11
  preventDefault: false,
11
12
  frequency: 1,
12
13
  debug: false,
@@ -33,7 +34,33 @@ function MpBackPlugin(userOptions: UserOptions = {}): Plugin {
33
34
  }
34
35
  // 导出一个对象
35
36
  if (id === virtualFileId) {
36
- return `export default function onPageBack() {}`
37
+ return `
38
+ import { ref } from 'vue'
39
+ export default function onPageBack() {}
40
+ export function activeMpBack(fn = null) {
41
+ fn?.()
42
+ }
43
+ export function inactiveMpBack(fn = null) {
44
+ fn?.()
45
+ }
46
+ export function useMpWeixinBack(initialValue = true) {
47
+ const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(initialValue)
48
+
49
+ const __MP_WEIXIN_ACTIVEBACK__ = () => {
50
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = true
51
+ }
52
+
53
+ const __MP_WEIXIN_INACTIVEBACK__ = () => {
54
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
55
+ }
56
+
57
+ return {
58
+ __MP_BACK_SHOW_PAGE_CONTAINER__,
59
+ __MP_WEIXIN_ACTIVEBACK__,
60
+ __MP_WEIXIN_INACTIVEBACK__
61
+ }
62
+ }
63
+ `
37
64
  }
38
65
  },
39
66
  async transform(code, id) {
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <div>我是默认的界面</div>
3
+ <button id="button" @click="disableMpBack"></button>
4
+ <button id="button2" @click="activeMpBack"></button>
5
+ </template>
6
+
7
+ <script setup>
8
+ import onPageBack, { activeMpBack as mpppacitve, inactiveMpBack } from 'mp-weixin-back-helper'
9
+
10
+ onPageBack(
11
+ () => {
12
+ console.log('触发了手势返回')
13
+ },
14
+ {
15
+ initialValue: false,
16
+ }
17
+ )
18
+
19
+ const activeMpBack = () => {
20
+ console.log('执行了activeMpBack')
21
+ mpppacitve()
22
+ }
23
+
24
+ const disableMpBack = () => {
25
+ inactiveMpBack()
26
+ }
27
+ </script>
28
+
29
+ <style></style>
@@ -1,31 +1,64 @@
1
- import { describe, expect, it } from 'vitest'
1
+ import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
2
2
  import { mount } from '@vue/test-utils'
3
- // @ts-ignore
4
3
  import IndexSetup from './data/index-setup.vue'
5
- // @ts-ignore
4
+ import IndexUtils from './data/index-utils.vue'
6
5
  import IndexDefault from './data/index-default.vue'
7
6
 
8
7
  describe('generate page-container components', () => {
9
- it('setup compisitionAPI', async () => {
10
- const wrapper = mount(IndexSetup)
11
- await wrapper.vm.$nextTick()
12
-
13
- const pageContainerRef = wrapper.find('page-container')
14
- expect(pageContainerRef.exists()).toBe(true)
15
- expect(wrapper.vm.__MP_BACK_SHOW_PAGE_CONTAINER__).toBe(true)
16
- expect(wrapper.vm.onBeforeLeave()).toBe(true)
8
+ let logSpy: ReturnType<typeof vi.spyOn>
9
+
10
+ beforeEach(() => {
11
+ logSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
12
+ })
13
+
14
+ afterEach(() => {
15
+ logSpy.mockRestore()
16
+ })
17
+
18
+ describe('setup compositionAPI', () => {
19
+ it('default case', async () => {
20
+ const wrapper = mount(IndexSetup)
21
+ await wrapper.vm.$nextTick()
22
+
23
+ const pageContainerRef = wrapper.find('page-container')
24
+ expect(pageContainerRef.exists()).toBe(true)
25
+ expect(wrapper.vm.__MP_BACK_SHOW_PAGE_CONTAINER__).toBe(true)
26
+ expect(typeof wrapper.vm.onBeforeLeave).toBe('function')
27
+ })
28
+
29
+ it('utils case', async () => {
30
+ const wrapper = mount(IndexUtils)
31
+ await wrapper.vm.$nextTick()
32
+
33
+ const pageContainerRef = wrapper.find('page-container')
34
+ expect(pageContainerRef.exists()).toBe(true)
35
+ expect(wrapper.vm.__MP_BACK_SHOW_PAGE_CONTAINER__).toBe(false)
36
+ expect(typeof wrapper.vm.onBeforeLeave).toBe('function')
37
+
38
+ await wrapper.find('#button2').trigger('click')
39
+ await new Promise(resolve => setTimeout(resolve, 0))
40
+
41
+ expect(logSpy).toHaveBeenCalledWith('执行了activeMpBack')
42
+
43
+ expect(wrapper.vm.__MP_BACK_SHOW_PAGE_CONTAINER__).toBe(true)
44
+
45
+ await wrapper.find('#button').trigger('click')
46
+ await new Promise(resolve => setTimeout(resolve, 0))
47
+
48
+ expect(wrapper.vm.__MP_BACK_SHOW_PAGE_CONTAINER__).toBe(false)
49
+ })
17
50
  })
18
51
 
19
- it('default optionsAPI', async () => {
20
- const wrapper = mount(IndexDefault)
21
- await wrapper.vm.$nextTick()
22
- const pageContainerRef = wrapper.find('page-container')
23
- expect(pageContainerRef.exists()).toBe(true)
24
- // @ts-ignore
25
- expect(wrapper.vm.__MP_BACK_SHOW_PAGE_CONTAINER__).toBe(true)
26
- // @ts-ignore
27
- expect(wrapper.vm.__MP_BACK_FREQUENCY__).toBe(1)
28
- // @ts-ignore
29
- expect(wrapper.vm.onBeforeLeave()).toBe(true)
52
+ describe('optionsAPI', () => {
53
+ it('default case', async () => {
54
+ const wrapper = mount(IndexDefault)
55
+ await wrapper.vm.$nextTick()
56
+
57
+ const pageContainerRef = wrapper.find('page-container')
58
+ expect(pageContainerRef.exists()).toBe(true)
59
+ expect(wrapper.vm.__MP_BACK_SHOW_PAGE_CONTAINER__).toBe(true)
60
+ expect(wrapper.vm.__MP_BACK_FREQUENCY__).toBe(1)
61
+ expect(wrapper.vm.onBeforeLeave()).toBe(true)
62
+ })
30
63
  })
31
64
  })
package/types/index.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  export type UserOptions = Partial<Config>
2
2
 
3
3
  export type Config = {
4
+ /**
5
+ * 初始化时是否监听手势返回,默认值为`true`
6
+ */
7
+ initialValue: boolean
4
8
  /**
5
9
  * 是否阻止默认的回退事件,默认为 false
6
10
  */
package/utils/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { parse } from '@vue/compiler-sfc'
2
2
  import { pageContext } from '../src/context'
3
3
  import { vueWalker } from './walker'
4
- import type { SFCDescriptor } from '@vue/compiler-sfc'
5
4
 
6
5
  export async function transformVueFile(this: pageContext, code: string, id: string) {
7
6
  try {
package/utils/walker.ts CHANGED
@@ -4,7 +4,9 @@ import { babelParse, walkAST } from 'ast-kit'
4
4
  import { pageContext } from '../src/context'
5
5
  import { virtualFileId } from './constant'
6
6
  import type {
7
+ WithStatement,
7
8
  BlockStatement,
9
+ Statement,
8
10
  FunctionExpression,
9
11
  Node,
10
12
  ObjectExpression,
@@ -29,17 +31,42 @@ function compositionWalk(context: pageContext, code: string, sfc: any, id: strin
29
31
  pageBackFnName: 'onPageBack',
30
32
  hasImportRef: false,
31
33
  backConfig: { ...context.config },
32
- callbackCode: '',
34
+ onPageBackBodyAst: [] as Statement[],
35
+ onPageBackCallNodeToRemove: null as Node | null,
36
+ activeFnName: 'activeMpBack',
37
+ inActiveFnName: 'inactiveMpBack',
33
38
  }
34
39
 
40
+ const activeFnCallsToModify: any[] = []
41
+ const inActiveFnCallsToModify: any[] = []
42
+
35
43
  if (setupAst) {
36
44
  walkAST<Node>(setupAst, {
37
45
  enter(node) {
38
46
  if (node.type === 'ImportDeclaration') {
39
47
  if (node.source.value.includes(virtualFileId)) {
40
- const importSpecifier = node.specifiers[0]
48
+ const importDefaultSpecifiers = node.specifiers.filter(
49
+ (i) => i.type === 'ImportDefaultSpecifier'
50
+ )
51
+ const importDefaultSpecifier = importDefaultSpecifiers[0]
41
52
  pageInfo.hasPageBack = true
42
- pageInfo.pageBackFnName = importSpecifier.local.name
53
+ pageInfo.pageBackFnName = importDefaultSpecifier.local.name
54
+
55
+ const importSpecifiers = node.specifiers.filter((i) => i.type === 'ImportSpecifier')
56
+ importSpecifiers.map((specifiers) => {
57
+ if (
58
+ specifiers.imported.type === 'Identifier' &&
59
+ specifiers.imported.name === 'activeMpBack'
60
+ ) {
61
+ pageInfo.activeFnName = specifiers.local.name
62
+ }
63
+ if (
64
+ specifiers.imported.type === 'Identifier' &&
65
+ specifiers.imported.name === 'inactiveMpBack'
66
+ ) {
67
+ pageInfo.inActiveFnName = specifiers.local.name
68
+ }
69
+ })
43
70
  }
44
71
  if (node.source.value === 'vue') {
45
72
  node.specifiers.some((specifier) => {
@@ -57,6 +84,8 @@ function compositionWalk(context: pageContext, code: string, sfc: any, id: strin
57
84
  node.expression.type === 'CallExpression' &&
58
85
  node.expression.callee.loc?.identifierName === pageInfo.pageBackFnName
59
86
  ) {
87
+ // 记录下整个 onPageBack(...) 语句节点,以便后续移除
88
+ pageInfo.onPageBackCallNodeToRemove = node
60
89
  const callback = node.expression.arguments[0]
61
90
  const backArguments = node.expression.arguments[1]
62
91
 
@@ -72,16 +101,43 @@ function compositionWalk(context: pageContext, code: string, sfc: any, id: strin
72
101
  callback &&
73
102
  (callback.type === 'ArrowFunctionExpression' || callback.type === 'FunctionExpression')
74
103
  ) {
75
- const body = callback.body
76
- if (body.type === 'BlockStatement') {
77
- pageInfo.callbackCode += body.body
78
- .map(
79
- // @ts-ignore
80
- (statement) => (generate.default ? generate.default : generate)(statement).code
81
- )
82
- .join('')
83
- }
104
+ pageInfo.onPageBackBodyAst = callback.body.body
84
105
  }
106
+
107
+ // 跳过此节点的子节点遍历,因为我们将手动处理其内部逻辑
108
+ return
109
+ }
110
+
111
+ if (
112
+ node.type === 'ExpressionStatement' &&
113
+ node.expression.type === 'CallExpression' &&
114
+ node.expression.callee.loc?.identifierName === pageInfo.activeFnName
115
+ ) {
116
+ activeFnCallsToModify.push({
117
+ start: node.expression.start,
118
+ end: node.expression.end,
119
+ original: sfc.scriptSetup!.loc.source.substring(
120
+ node.expression.start,
121
+ node.expression.end
122
+ ),
123
+ name: pageInfo.activeFnName,
124
+ })
125
+ }
126
+
127
+ if (
128
+ node.type === 'ExpressionStatement' &&
129
+ node.expression.type === 'CallExpression' &&
130
+ node.expression.callee.loc?.identifierName === pageInfo.inActiveFnName
131
+ ) {
132
+ inActiveFnCallsToModify.push({
133
+ start: node.expression.start,
134
+ end: node.expression.end,
135
+ original: sfc.scriptSetup!.loc.source.substring(
136
+ node.expression.start,
137
+ node.expression.end
138
+ ),
139
+ name: pageInfo.inActiveFnName,
140
+ })
85
141
  }
86
142
  },
87
143
  })
@@ -90,18 +146,59 @@ function compositionWalk(context: pageContext, code: string, sfc: any, id: strin
90
146
  // 没有引入mp-weixin-back-helper
91
147
  if (!pageInfo.hasPageBack) return code
92
148
 
149
+ if (pageInfo.onPageBackCallNodeToRemove) {
150
+ const scriptSetupOffset = sfc.scriptSetup!.loc.start.offset
151
+ const nodeToRemove = pageInfo.onPageBackCallNodeToRemove as any
152
+ const globalStart = scriptSetupOffset + nodeToRemove.start
153
+ const globalEnd = scriptSetupOffset + nodeToRemove.end
154
+ codeMs.remove(globalStart, globalEnd)
155
+ }
156
+
157
+ let callbackCode = ''
158
+ if (pageInfo.onPageBackBodyAst.length > 0) {
159
+ // 包装成一个临时的 AST 根节点以供遍历
160
+ const tempAstRoot = {
161
+ type: 'BlockStatement',
162
+ body: pageInfo.onPageBackBodyAst,
163
+ } as WithStatement
164
+
165
+ walkAST(tempAstRoot, {
166
+ enter(node: any) {
167
+ if (node.type === 'CallExpression' && node.callee.type === 'Identifier') {
168
+ const createIdentifier = (name: string) => ({ type: 'Identifier', name })
169
+
170
+ if (node.callee.name === pageInfo.activeFnName) {
171
+ node.arguments.unshift(createIdentifier('__MP_WEIXIN_ACTIVEBACK__'))
172
+ } else if (node.callee.name === pageInfo.inActiveFnName) {
173
+ node.arguments.unshift(createIdentifier('__MP_WEIXIN_INACTIVEBACK__'))
174
+ }
175
+ }
176
+ },
177
+ })
178
+
179
+ callbackCode = pageInfo.onPageBackBodyAst
180
+ // @ts-ignore
181
+ .map((statement) => (generate.default ? generate.default : generate)(statement).code)
182
+ .join('\n')
183
+ }
184
+
93
185
  if (code.includes('<page-container')) {
94
186
  context.log.debugLog(`${context.getPageById(id)}页面已有page-container组件,注入失败`)
95
187
  return code
96
188
  }
97
189
 
98
190
  if (!pageInfo.backConfig.preventDefault) {
99
- pageInfo.callbackCode += 'uni.navigateBack({ delta: 1 });'
191
+ callbackCode += 'uni.navigateBack({ delta: 1 });'
100
192
  }
101
193
 
194
+ const importUseMpWeixinBack = `import { useMpWeixinBack } from '${virtualFileId}'`
102
195
  const importRefFromVue = !pageInfo.hasImportRef ? `import { ref } from 'vue'` : ''
103
196
  const stateFrequency = 'let __MP_BACK_FREQUENCY__ = 1;'
104
- const statePageContainerVar = 'const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(true);'
197
+
198
+ const statePageContainerVar = `
199
+ const { __MP_BACK_SHOW_PAGE_CONTAINER__, __MP_WEIXIN_ACTIVEBACK__, __MP_WEIXIN_INACTIVEBACK__ } = useMpWeixinBack(${pageInfo.backConfig.initialValue})
200
+ `
201
+
105
202
  // 获取传入插件的统一方法
106
203
  const configBack = (() => {
107
204
  const onPageBack = pageInfo.backConfig.onPageBack
@@ -115,15 +212,19 @@ function compositionWalk(context: pageContext, code: string, sfc: any, id: strin
115
212
  }
116
213
  return `(function ${onPageBack})()`
117
214
  })()
215
+
118
216
  const stateBeforeLeave = `
119
217
  const onBeforeLeave = () => {
218
+ if (!__MP_BACK_SHOW_PAGE_CONTAINER__.value) {
219
+ return
220
+ }
120
221
  if (__MP_BACK_FREQUENCY__ < ${pageInfo.backConfig.frequency}) {
121
222
  __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
122
223
  setTimeout(() => __MP_BACK_SHOW_PAGE_CONTAINER__.value = true, 0);
123
224
  __MP_BACK_FREQUENCY__++
124
225
  }
125
226
  ${configBack}
126
- ${pageInfo.callbackCode}
227
+ ${callbackCode}
127
228
  };
128
229
  `
129
230
  const { template, scriptSetup } = sfc
@@ -147,10 +248,43 @@ function compositionWalk(context: pageContext, code: string, sfc: any, id: strin
147
248
  const scriptMagicString = new MagicString(scriptOffsets.content)
148
249
  scriptMagicString.prepend(
149
250
  ` ${importRefFromVue}
251
+ ${importUseMpWeixinBack}
150
252
  ${stateFrequency}
151
253
  ${statePageContainerVar}
152
254
  ${stateBeforeLeave} `
153
255
  )
256
+
257
+ // 应用 activeMpBack 调用的修改
258
+ activeFnCallsToModify.forEach((call) => {
259
+ // 使用正则匹配函数调用结构,确保我们只修改括号内的内容
260
+ const fnCallRegex = new RegExp(`${call.name}\\(([^)]*)\\)`, 'g')
261
+ const newCall = call.original.replace(fnCallRegex, (_match: any, args: string) => {
262
+ // 如果原调用没有参数
263
+ if (!args.trim()) {
264
+ return `${call.name}(__MP_WEIXIN_ACTIVEBACK__)`
265
+ }
266
+ // 如果有参数,添加新参数
267
+ return `${call.name}(__MP_WEIXIN_ACTIVEBACK__, ${args})`
268
+ })
269
+
270
+ scriptMagicString.overwrite(call.start, call.end, newCall)
271
+ })
272
+
273
+ inActiveFnCallsToModify.forEach((call) => {
274
+ // 使用正则匹配函数调用结构,确保我们只修改括号内的内容
275
+ const fnCallRegex = new RegExp(`${call.name}\\(([^)]*)\\)`, 'g')
276
+ const newCall = call.original.replace(fnCallRegex, (_match: any, args: string) => {
277
+ // 如果原调用没有参数
278
+ if (!args.trim()) {
279
+ return `${call.name}(__MP_WEIXIN_INACTIVEBACK__)`
280
+ }
281
+ // 如果有参数,添加新参数
282
+ return `${call.name}(__MP_WEIXIN_INACTIVEBACK__, ${args})`
283
+ })
284
+
285
+ scriptMagicString.overwrite(call.start, call.end, newCall)
286
+ })
287
+
154
288
  codeMs.overwrite(scriptOffsets.start, scriptOffsets.end, scriptMagicString.toString())
155
289
 
156
290
  return codeMs.toString()
@@ -284,7 +418,7 @@ function optionsWalk(context: pageContext, code: string, sfc: any, id: string) {
284
418
  ],
285
419
  },
286
420
  }
287
- ; (exportDefaultNode as ObjectExpression).properties.push(addData)
421
+ ;(exportDefaultNode as ObjectExpression).properties.push(addData)
288
422
  }
289
423
 
290
424
  // 获取传入插件的统一方法
@@ -340,7 +474,7 @@ function optionsWalk(context: pageContext, code: string, sfc: any, id: string) {
340
474
  },
341
475
  } as ObjectMethod
342
476
  if (methodsNode) {
343
- ; (methodsNode as ObjectExpression).properties.push(newMethodsProperty)
477
+ ;(methodsNode as ObjectExpression).properties.push(newMethodsProperty)
344
478
  } else if (exportDefaultNode) {
345
479
  const addMethods: ObjectProperty = {
346
480
  type: 'ObjectProperty',
@@ -355,7 +489,7 @@ function optionsWalk(context: pageContext, code: string, sfc: any, id: string) {
355
489
  properties: [newMethodsProperty],
356
490
  },
357
491
  }
358
- ; (exportDefaultNode as ObjectExpression).properties.push(addMethods)
492
+ ;(exportDefaultNode as ObjectExpression).properties.push(addMethods)
359
493
  }
360
494
 
361
495
  const { template, script } = sfc
package/vite.config.ts CHANGED
@@ -3,7 +3,16 @@ import vue from '@vitejs/plugin-vue'
3
3
  import mpBack from './dist/index.mjs'
4
4
 
5
5
  export default defineConfig({
6
- plugins: [mpBack(), vue()],
6
+ plugins: [
7
+ mpBack(),
8
+ vue({
9
+ template: {
10
+ compilerOptions: {
11
+ isCustomElement: (tag) => tag.startsWith('page-') || tag.startsWith('mp-'),
12
+ },
13
+ },
14
+ }),
15
+ ],
7
16
  test: {
8
17
  environment: 'happy-dom',
9
18
  },