Skip to content

Commit 783e29c

Browse files
authored
Merge pull request #4825 from easyops-cn/steve/v3-sibling-routes
fix(): handle sibling routes matching order
2 parents 3ccc031 + b64d8bd commit 783e29c

File tree

3 files changed

+52
-20
lines changed

3 files changed

+52
-20
lines changed

packages/runtime/src/internal/Renderer.ts

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import type {
5252
RenderReturnNode,
5353
RuntimeBrickConfWithSymbols,
5454
RuntimeContext,
55+
RouteNode,
5556
} from "./interfaces.js";
5657
import {
5758
getTagNameOfCustomTemplate,
@@ -99,7 +100,7 @@ export async function renderRoutes(
99100
routes: RouteConf[],
100101
_runtimeContext: RuntimeContext,
101102
rendererContext: RendererContext,
102-
parentRoutes: RouteConf[],
103+
parentRoutes: RouteNode[],
103104
menuRequestReturnNode: MenuRequestNode,
104105
slotId?: string,
105106
isIncremental?: boolean,
@@ -131,7 +132,7 @@ export async function renderRoutes(
131132
if (isIncremental) {
132133
runtimeContext.ctxStore.disposeDataInRoutes(routes);
133134
}
134-
const routePath = parentRoutes.concat(route);
135+
const routePath = parentRoutes.concat({ route, routes });
135136
runtimeContext.ctxStore.define(
136137
route.context,
137138
runtimeContext,
@@ -246,7 +247,7 @@ export async function renderBricks(
246247
bricks: BrickConf[],
247248
runtimeContext: RuntimeContext,
248249
rendererContext: RendererContext,
249-
parentRoutes: RouteConf[],
250+
parentRoutes: RouteNode[],
250251
menuRequestReturnNode: MenuRequestNode,
251252
slotId?: string,
252253
tplStack?: Map<string, number>,
@@ -283,7 +284,7 @@ export async function renderBrick(
283284
brickConf: RuntimeBrickConfWithSymbols,
284285
_runtimeContext: RuntimeContext,
285286
rendererContext: RendererContext,
286-
parentRoutes: RouteConf[],
287+
parentRoutes: RouteNode[],
287288
menuRequestReturnNode: MenuRequestNode,
288289
slotId?: string,
289290
tplStack = new Map<string, number>(),
@@ -320,7 +321,7 @@ async function legacyRenderBrick(
320321
brickConf: RuntimeBrickConfWithSymbols,
321322
_runtimeContext: RuntimeContext,
322323
rendererContext: RendererContext,
323-
parentRoutes: RouteConf[],
324+
parentRoutes: RouteNode[],
324325
menuRequestReturnNode: MenuRequestNode,
325326
slotId: string | undefined,
326327
tplStack: Map<string, number>,
@@ -912,30 +913,34 @@ async function legacyRenderBrick(
912913
};
913914
lastOutput.node = abstractNode;
914915

915-
const parentRoute = parentRoutes[parentRoutes.length - 1] as
916-
| RouteConfOfBricks
917-
| undefined;
918-
if (parentRoute?.incrementalSubRoutes) {
916+
const { route: parentRoute } = parentRoutes[parentRoutes.length - 1];
917+
if ((parentRoute as RouteConfOfBricks)?.incrementalSubRoutes) {
919918
routeSlotFromIndexToSlotId.set(index, childSlotId);
920919
rendererContext.performIncrementalRender(
921920
slotConf,
922-
parentRoutes,
921+
parentRoutes.map(({ route }) => route),
923922
async (location, prevLocation) => {
924923
const { homepage } = childRuntimeContext.app;
925924
const { pathname } = location;
926925
// Ignore if any one of homepage and parent routes not matched.
927926
if (
928927
!matchHomepage(homepage, pathname) ||
929-
!parentRoutes.every((route) => {
930-
let prevMatch: MatchResult | null;
931-
let newMatch: MatchResult | null;
928+
!parentRoutes.every(({ route, routes }) => {
929+
let prevMatch: MatchResult | null = null;
930+
let newMatch: MatchResult | null = null;
932931
return (
933-
(prevMatch = matchRoute(
932+
(prevMatch = matchTargetRoute(
934933
route,
934+
routes,
935935
homepage,
936936
prevLocation.pathname
937937
)) &&
938-
(newMatch = matchRoute(route, homepage, pathname)) &&
938+
(newMatch = matchTargetRoute(
939+
route,
940+
routes,
941+
homepage,
942+
pathname
943+
)) &&
939944
(route !== parentRoute ||
940945
isRouteParamsEqual(prevMatch.params, newMatch.params))
941946
);
@@ -1124,7 +1129,7 @@ async function renderForEach(
11241129
bricks: BrickConf[],
11251130
runtimeContext: RuntimeContext,
11261131
rendererContext: RendererContext,
1127-
parentRoutes: RouteConf[],
1132+
parentRoutes: RouteNode[],
11281133
menuRequestReturnNode: MenuRequestNode,
11291134
slotId: string | undefined,
11301135
tplStack: Map<string, number>,
@@ -1369,3 +1374,23 @@ function isRouteParamsEqual(
13691374
function isRouteConf(child: BrickConf | RouteConf): child is RouteConf {
13701375
return !!(child as RouteConf).path && !(child as BrickConf).brick;
13711376
}
1377+
1378+
/**
1379+
* Find the first matched route among siblings.
1380+
*
1381+
* Return the match result only if it matches the target route.
1382+
*/
1383+
function matchTargetRoute(
1384+
route: RouteConf,
1385+
routes: RouteConf[],
1386+
homepage: string,
1387+
pathname: string
1388+
) {
1389+
for (const sibling of routes) {
1390+
const match = matchRoute(sibling, homepage, pathname);
1391+
if (match) {
1392+
return sibling === route ? match : null;
1393+
}
1394+
}
1395+
return null;
1396+
}

packages/runtime/src/internal/data/DataStore.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { ResolveOptions, resolveData } from "./resolveData.js";
1919
import { resolveDataStore } from "./resolveDataStore.js";
2020
import type {
2121
AsyncPropertyEntry,
22+
RouteNode,
2223
RuntimeBrick,
2324
RuntimeContext,
2425
} from "../interfaces.js";
@@ -330,7 +331,7 @@ export class DataStore<T extends DataStoreType = "CTX"> {
330331
dataConfs: ContextConf[] | undefined,
331332
runtimeContext: RuntimeContext,
332333
asyncHostPropertyEntries?: AsyncPropertyEntry[],
333-
routePath?: RouteConf[]
334+
routePath?: RouteNode[]
334335
): void {
335336
if (Array.isArray(dataConfs) && dataConfs.length > 0) {
336337
const pending = resolveDataStore(
@@ -346,7 +347,7 @@ export class DataStore<T extends DataStoreType = "CTX"> {
346347
isStrictMode(runtimeContext)
347348
);
348349
if (Array.isArray(routePath)) {
349-
for (const route of routePath) {
350+
for (const { route } of routePath) {
350351
const stack = this.routeStackMap.get(route);
351352
if (stack) {
352353
stack.add(pending);
@@ -414,7 +415,7 @@ export class DataStore<T extends DataStoreType = "CTX"> {
414415
dataConf: ContextConf,
415416
runtimeContext: RuntimeContext,
416417
asyncHostPropertyEntries?: AsyncPropertyEntry[],
417-
routePath?: RouteConf[]
418+
routePath?: RouteNode[]
418419
): Promise<boolean> {
419420
if (!(await asyncCheckIf(dataConf, runtimeContext))) {
420421
return false;
@@ -565,7 +566,7 @@ export class DataStore<T extends DataStoreType = "CTX"> {
565566
this.data.set(dataConf.name, newData);
566567

567568
if (Array.isArray(routePath)) {
568-
for (const route of routePath) {
569+
for (const { route } of routePath) {
569570
const names = this.routeMap.get(route);
570571
if (names) {
571572
names.add(dataConf.name);

packages/runtime/src/internal/interfaces.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,9 @@ export interface RuntimeDataVale
203203
export interface RuntimeDataValueOption {
204204
routeId?: string;
205205
}
206+
207+
export interface RouteNode {
208+
route: RouteConf;
209+
// All ordered sibling routes under the same parent including the route itself
210+
routes: RouteConf[];
211+
}

0 commit comments

Comments
 (0)