@@ -32,6 +32,7 @@ import {
32
32
} from './core'
33
33
import {
34
34
dispatchNativeEvent ,
35
+ dispatchPopStateEventToMicroApp ,
35
36
} from './event'
36
37
import {
37
38
updateMicroLocation ,
@@ -44,15 +45,68 @@ import {
44
45
isIframeSandbox ,
45
46
} from '../../create_app'
46
47
48
+ interface HistoryStack {
49
+ [ appName : string ] : {
50
+ stack : Array < { path : string , state : any } > ,
51
+ currentIndex : number
52
+ }
53
+ }
54
+ const pureHistoryStack : HistoryStack = { }
55
+
56
+ function initPureHistory ( appName : string ) : void {
57
+ if ( ! pureHistoryStack [ appName ] ) {
58
+ pureHistoryStack [ appName ] = {
59
+ stack : [ ] ,
60
+ currentIndex : - 1
61
+ }
62
+ }
63
+ }
64
+
65
+ function addToPureHistory ( appName : string , path : string , state : any ) : void {
66
+ if ( ! pureHistoryStack [ appName ] ) {
67
+ pureHistoryStack [ appName ] = {
68
+ stack : [ ] ,
69
+ currentIndex : - 1
70
+ }
71
+ }
72
+ const history = pureHistoryStack [ appName ]
73
+ // 处理路径,移除基础路径
74
+ const basePath = `/${ appName } /`
75
+ const cleanPath = path . startsWith ( basePath ) ? path . slice ( basePath . length - 1 ) : path
76
+
77
+ // 检查是否与当前路径相同
78
+ const currentEntry = history . stack [ history . currentIndex ]
79
+ if ( currentEntry && currentEntry . path === cleanPath ) {
80
+ // 如果路径相同,只更新状态
81
+ currentEntry . state = state
82
+ return
83
+ }
84
+
85
+ if ( history . currentIndex < history . stack . length - 1 ) {
86
+ history . stack = history . stack . slice ( 0 , history . currentIndex + 1 )
87
+ }
88
+
89
+ history . stack . push ( {
90
+ path : cleanPath ,
91
+ state
92
+ } )
93
+ history . currentIndex ++
94
+ }
95
+
96
+ export function clearPureHistory ( appName : string ) : void {
97
+ delete pureHistoryStack [ appName ]
98
+ }
99
+
47
100
/**
48
101
* create proxyHistory for microApp
49
102
* MDN https://developer.mozilla.org/en-US/docs/Web/API/History
50
103
* @param appName app name
51
104
* @param microLocation microApp location(with: proxyLocation iframe: iframeWindow.location)
52
105
*/
53
- export function createMicroHistory ( appName : string , microLocation : MicroLocation ) : MicroHistory {
106
+ export function createMicroHistory ( appName : string , microLocation : MicroLocation ) : MicroHistory {
54
107
const rawHistory = globalEnv . rawWindow . history
55
- function getMicroHistoryMethod ( methodName : string ) : CallableFunction {
108
+ initPureHistory ( appName )
109
+ function getMicroHistoryMethod ( methodName : string ) : CallableFunction {
56
110
return function ( ...rests : any [ ] ) : void {
57
111
// TODO: 测试iframe的URL兼容isURL的情况
58
112
rests [ 2 ] = isUndefined ( rests [ 2 ] ) || isNull ( rests [ 2 ] ) || ( '' + rests [ 2 ] === '' ) ? microLocation . href : '' + rests [ 2 ]
@@ -67,6 +121,8 @@ export function createMicroHistory (appName: string, microLocation: MicroLocatio
67
121
setMicroState ( appName , rests [ 0 ] , targetLocation ) ,
68
122
rests [ 1 ] ,
69
123
)
124
+ } else {
125
+ addToPureHistory ( appName , targetFullPath , rests [ 0 ] )
70
126
}
71
127
if ( targetFullPath !== microLocation . fullPath ) {
72
128
updateMicroLocation ( appName , targetFullPath , microLocation )
@@ -82,22 +138,52 @@ export function createMicroHistory (appName: string, microLocation: MicroLocatio
82
138
83
139
if ( isIframeSandbox ( appName ) ) {
84
140
return assign ( {
85
- go ( delta ?: number ) {
86
- return rawHistory . go ( delta )
87
- }
141
+ go ( delta ?: number ) {
142
+ if ( ! isRouterModePure ( appName ) ) {
143
+ return rawHistory . go ( delta )
144
+ }
145
+ const history = pureHistoryStack [ appName ]
146
+ const targetIndex = history . currentIndex + ( delta || 0 )
147
+ if ( targetIndex === history . currentIndex ) {
148
+ return
149
+ }
150
+ const target = history . stack [ targetIndex ]
151
+ history . currentIndex = targetIndex
152
+ updateMicroLocation (
153
+ appName ,
154
+ target . path ,
155
+ microLocation ,
156
+ 'pure-history'
157
+ )
158
+ const app = appInstanceMap . get ( appName )
159
+ if ( app ?. sandBox ) {
160
+ // 最后触发事件
161
+ dispatchPopStateEventToMicroApp (
162
+ appName ,
163
+ app . sandBox . proxyWindow ,
164
+ app . sandBox . microAppWindow
165
+ )
166
+ }
167
+ } ,
168
+ back ( ) {
169
+ this . go ( - 1 )
170
+ } ,
171
+ forward ( ) {
172
+ this . go ( 1 )
173
+ } ,
88
174
} , originalHistory ) as MicroHistory
89
175
}
90
176
91
177
return new Proxy ( rawHistory , {
92
- get ( target : History , key : PropertyKey ) : HistoryProxyValue {
178
+ get ( target : History , key : PropertyKey ) : HistoryProxyValue {
93
179
if ( key === 'pushState' || key === 'replaceState' ) {
94
180
return originalHistory [ key ]
95
181
} else if ( key === 'state' ) {
96
182
return getMicroState ( appName )
97
183
}
98
184
return bindFunctionToRawTarget < History , HistoryProxyValue > ( Reflect . get ( target , key ) , target , 'HISTORY' )
99
185
} ,
100
- set ( target : History , key : PropertyKey , value : unknown ) : boolean {
186
+ set ( target : History , key : PropertyKey , value : unknown ) : boolean {
101
187
if ( key === 'pushState' || key === 'replaceState' ) {
102
188
originalHistory [ key ] = value as CallableFunction
103
189
} else {
@@ -121,7 +207,7 @@ export function createMicroHistory (appName: string, microLocation: MicroLocatio
121
207
* @param state history.state, default is null
122
208
* @param title history.title, default is ''
123
209
*/
124
- export function nativeHistoryNavigate (
210
+ export function nativeHistoryNavigate (
125
211
appName : string ,
126
212
methodName : string ,
127
213
fullPath : string ,
@@ -150,7 +236,7 @@ export function nativeHistoryNavigate (
150
236
* @param state history.state, not required
151
237
* @param title history.title, not required
152
238
*/
153
- export function navigateWithNativeEvent (
239
+ export function navigateWithNativeEvent (
154
240
appName : string ,
155
241
methodName : string ,
156
242
result : HandleMicroPathResult ,
@@ -179,7 +265,7 @@ export function navigateWithNativeEvent (
179
265
* @param result result of add/remove microApp path on browser url
180
266
* @param state history.state
181
267
*/
182
- export function attachRouteToBrowserURL (
268
+ export function attachRouteToBrowserURL (
183
269
appName : string ,
184
270
result : HandleMicroPathResult ,
185
271
state : MicroState ,
@@ -192,7 +278,7 @@ export function attachRouteToBrowserURL (
192
278
* Fix bug of missing __MICRO_APP_STATE__ when base app is next.js or angular
193
279
* @param method history.pushState/replaceState
194
280
*/
195
- function reWriteHistoryMethod ( method : History [ 'pushState' | 'replaceState' ] ) : CallableFunction {
281
+ function reWriteHistoryMethod ( method : History [ 'pushState' | 'replaceState' ] ) : CallableFunction {
196
282
const rawWindow = globalEnv . rawWindow
197
283
return function ( ...rests : [ data : any , unused : string , url ?: string ] ) : void {
198
284
if (
@@ -213,9 +299,9 @@ function reWriteHistoryMethod (method: History['pushState' | 'replaceState']): C
213
299
/**
214
300
* Attach child router info to browser url when base app navigate with pushState/replaceState
215
301
* NOTE:
216
- * 1. Exec after apply pushState/replaceState
217
- * 2. Unable to catch when base app navigate with location
218
- * 3. When in nest app, rawPushState/rawReplaceState has been modified by parent
302
+ * 1. Exec after apply pushState/replaceState
303
+ * 2. Unable to catch when base app navigate with location
304
+ * 3. When in nest app, rawPushState/rawReplaceState has been modified by parent
219
305
*/
220
306
getActiveApps ( {
221
307
excludeHiddenApp : true ,
@@ -262,7 +348,7 @@ function reWriteHistoryMethod (method: History['pushState' | 'replaceState']): C
262
348
* used to fix the problem that the __MICRO_APP_STATE__ maybe missing when mainApp navigate to same path
263
349
* e.g: when nextjs, angular receive popstate event, they will use history.replaceState to update browser url with a new state object
264
350
*/
265
- export function patchHistory ( ) : void {
351
+ export function patchHistory ( ) : void {
266
352
const rawWindow = globalEnv . rawWindow
267
353
rawWindow . history . pushState = reWriteHistoryMethod (
268
354
globalEnv . rawPushState ,
@@ -272,7 +358,7 @@ export function patchHistory (): void {
272
358
)
273
359
}
274
360
275
- export function releasePatchHistory ( ) : void {
361
+ export function releasePatchHistory ( ) : void {
276
362
const rawWindow = globalEnv . rawWindow
277
363
rawWindow . history . pushState = globalEnv . rawPushState
278
364
rawWindow . history . replaceState = globalEnv . rawReplaceState
0 commit comments