mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
misc update on router
1. update example page's title 2. pass params to ImplWrapper(currently not pass it to the component, need discussion on it)
This commit is contained in:
parent
619e86e526
commit
5bfc886b31
@ -6,7 +6,7 @@
|
||||
<script>
|
||||
delete window.history;
|
||||
</script>
|
||||
<title>meta-ui runtime example: nested components</title>
|
||||
<title>meta-ui runtime example: hash router</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>meta-ui runtime example: nested components</title>
|
||||
<title>meta-ui runtime example: nested hash router</title>
|
||||
<script>
|
||||
delete window.history;
|
||||
</script>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>meta-ui runtime example: nested components</title>
|
||||
<title>meta-ui runtime example: history router</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>meta-ui runtime example: nested components</title>
|
||||
<title>meta-ui runtime example: nested router</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
@ -30,146 +30,155 @@ const ImplWrapper = React.forwardRef<
|
||||
routerMap: RouterComponentMap | undefined;
|
||||
targetSlot: { id: string; slot: string } | null;
|
||||
app: RuntimeApplication;
|
||||
[key: string]: any;
|
||||
}
|
||||
>(({ component: c, slotsMap, routerMap, targetSlot, app, ...props }, ref) => {
|
||||
// TODO: find better way to add barrier
|
||||
if (!stateStore[c.id]) {
|
||||
stateStore[c.id] = {};
|
||||
}
|
||||
>(
|
||||
(
|
||||
{ component: c, slotsMap, routerMap, targetSlot, app, children, ...props },
|
||||
ref
|
||||
) => {
|
||||
// TODO: find better way to add barrier
|
||||
if (!stateStore[c.id]) {
|
||||
stateStore[c.id] = {};
|
||||
}
|
||||
|
||||
const Impl = registry.getComponent(c.parsedType.version, c.parsedType.name)
|
||||
.impl;
|
||||
const Impl = registry.getComponent(c.parsedType.version, c.parsedType.name)
|
||||
.impl;
|
||||
|
||||
const handlerMap = useRef<Record<string, (parameters?: any) => void>>({});
|
||||
useEffect(() => {
|
||||
const handler = (s: {
|
||||
componentId: string;
|
||||
name: string;
|
||||
parameters?: any;
|
||||
}) => {
|
||||
if (s.componentId !== c.id) {
|
||||
return;
|
||||
}
|
||||
if (!handlerMap.current[s.name]) {
|
||||
// maybe log?
|
||||
return;
|
||||
}
|
||||
handlerMap.current[s.name](s.parameters);
|
||||
};
|
||||
apiService.on("uiMethod", handler);
|
||||
return () => {
|
||||
apiService.off("uiMethod", handler);
|
||||
};
|
||||
}, []);
|
||||
const handlerMap = useRef<Record<string, (parameters?: any) => void>>({});
|
||||
useEffect(() => {
|
||||
const handler = (s: {
|
||||
componentId: string;
|
||||
name: string;
|
||||
parameters?: any;
|
||||
}) => {
|
||||
if (s.componentId !== c.id) {
|
||||
return;
|
||||
}
|
||||
if (!handlerMap.current[s.name]) {
|
||||
// maybe log?
|
||||
return;
|
||||
}
|
||||
handlerMap.current[s.name](s.parameters);
|
||||
};
|
||||
apiService.on("uiMethod", handler);
|
||||
return () => {
|
||||
apiService.off("uiMethod", handler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const mergeState = useCallback(
|
||||
(partial: any) => {
|
||||
stateStore[c.id] = { ...stateStore[c.id], ...partial };
|
||||
},
|
||||
[c.id]
|
||||
);
|
||||
const mergeState = useCallback(
|
||||
(partial: any) => {
|
||||
stateStore[c.id] = { ...stateStore[c.id], ...partial };
|
||||
},
|
||||
[c.id]
|
||||
);
|
||||
|
||||
const subscribeMethods = useCallback(
|
||||
(map: any) => {
|
||||
handlerMap.current = merge(handlerMap.current, map);
|
||||
},
|
||||
[handlerMap.current]
|
||||
);
|
||||
const subscribeMethods = useCallback(
|
||||
(map: any) => {
|
||||
handlerMap.current = merge(handlerMap.current, map);
|
||||
},
|
||||
[handlerMap.current]
|
||||
);
|
||||
|
||||
// traits
|
||||
const [traitPropertiesMap, setTraitPropertiesMap] = useState<
|
||||
Map<typeof c["traits"][0], object>
|
||||
>(
|
||||
c.traits.reduce((prev, cur) => {
|
||||
prev.set(cur, deepEval(cur.properties).result);
|
||||
return prev;
|
||||
}, new Map())
|
||||
);
|
||||
useEffect(() => {
|
||||
const stops: ReturnType<typeof watch>[] = [];
|
||||
for (const t of c.traits) {
|
||||
const { stop, result } = deepEval(t.properties, ({ result }) => {
|
||||
// traits
|
||||
const [traitPropertiesMap, setTraitPropertiesMap] = useState<
|
||||
Map<typeof c["traits"][0], object>
|
||||
>(
|
||||
c.traits.reduce((prev, cur) => {
|
||||
prev.set(cur, deepEval(cur.properties).result);
|
||||
return prev;
|
||||
}, new Map())
|
||||
);
|
||||
useEffect(() => {
|
||||
const stops: ReturnType<typeof watch>[] = [];
|
||||
for (const t of c.traits) {
|
||||
const { stop, result } = deepEval(t.properties, ({ result }) => {
|
||||
setTraitPropertiesMap(
|
||||
new Map(traitPropertiesMap.set(t, { ...result }))
|
||||
);
|
||||
});
|
||||
setTraitPropertiesMap(
|
||||
new Map(traitPropertiesMap.set(t, { ...result }))
|
||||
);
|
||||
stops.push(stop);
|
||||
}
|
||||
return () => stops.forEach((s) => s());
|
||||
}, []);
|
||||
|
||||
const traitsProps = {};
|
||||
const wrappers: React.FC[] = [];
|
||||
for (const t of c.traits) {
|
||||
const tImpl = registry.getTrait(t.parsedType.version, t.parsedType.name)
|
||||
.impl;
|
||||
const { props: tProps, component: Wrapper } = tImpl({
|
||||
...traitPropertiesMap.get(t),
|
||||
mergeState,
|
||||
subscribeMethods,
|
||||
});
|
||||
setTraitPropertiesMap(new Map(traitPropertiesMap.set(t, { ...result })));
|
||||
stops.push(stop);
|
||||
merge(traitsProps, tProps);
|
||||
if (Wrapper) {
|
||||
wrappers.push(Wrapper);
|
||||
}
|
||||
}
|
||||
return () => stops.forEach((s) => s());
|
||||
}, []);
|
||||
|
||||
const traitsProps = {};
|
||||
const wrappers: React.FC[] = [];
|
||||
for (const t of c.traits) {
|
||||
const tImpl = registry.getTrait(t.parsedType.version, t.parsedType.name)
|
||||
.impl;
|
||||
const { props: tProps, component: Wrapper } = tImpl({
|
||||
...traitPropertiesMap.get(t),
|
||||
mergeState,
|
||||
subscribeMethods,
|
||||
});
|
||||
merge(traitsProps, tProps);
|
||||
if (Wrapper) {
|
||||
wrappers.push(Wrapper);
|
||||
}
|
||||
}
|
||||
const [mergedProps, setMergedProps] = useState(
|
||||
deepEval({
|
||||
...c.properties,
|
||||
...traitsProps,
|
||||
}).result
|
||||
);
|
||||
useEffect(() => {
|
||||
const rawProps: Record<string, unknown> = {
|
||||
...c.properties,
|
||||
...traitsProps,
|
||||
};
|
||||
|
||||
const [mergedProps, setMergedProps] = useState(
|
||||
deepEval({
|
||||
...c.properties,
|
||||
...traitsProps,
|
||||
}).result
|
||||
);
|
||||
useEffect(() => {
|
||||
const rawProps: Record<string, unknown> = {
|
||||
...c.properties,
|
||||
...traitsProps,
|
||||
};
|
||||
const { stop, result } = deepEval(rawProps, ({ result }) => {
|
||||
setMergedProps({ ...result });
|
||||
});
|
||||
|
||||
const { stop, result } = deepEval(rawProps, ({ result }) => {
|
||||
setMergedProps({ ...result });
|
||||
});
|
||||
return stop;
|
||||
}, []);
|
||||
|
||||
setMergedProps({ ...result });
|
||||
return stop;
|
||||
}, []);
|
||||
let C = (
|
||||
<Impl
|
||||
key={c.id}
|
||||
{...mergedProps}
|
||||
{...props}
|
||||
mergeState={mergeState}
|
||||
subscribeMethods={subscribeMethods}
|
||||
slotsMap={slotsMap}
|
||||
routerMap={routerMap}
|
||||
/>
|
||||
);
|
||||
|
||||
let C = (
|
||||
<Impl
|
||||
key={c.id}
|
||||
{...mergedProps}
|
||||
mergeState={mergeState}
|
||||
subscribeMethods={subscribeMethods}
|
||||
slotsMap={slotsMap}
|
||||
routerMap={routerMap}
|
||||
/>
|
||||
);
|
||||
|
||||
while (wrappers.length) {
|
||||
const W = wrappers.pop()!;
|
||||
C = <W>{C}</W>;
|
||||
}
|
||||
|
||||
if (targetSlot) {
|
||||
const targetC = app.spec.components.find((c) => c.id === targetSlot.id);
|
||||
if (targetC?.parsedType.name === "grid_layout") {
|
||||
return (
|
||||
<div key={c.id} data-meta-ui-id={c.id} ref={ref} {...props}>
|
||||
{C}
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
while (wrappers.length) {
|
||||
const W = wrappers.pop()!;
|
||||
C = <W>{C}</W>;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment key={c.id}>
|
||||
{C}
|
||||
{props.children}
|
||||
</React.Fragment>
|
||||
);
|
||||
});
|
||||
if (targetSlot) {
|
||||
const targetC = app.spec.components.find((c) => c.id === targetSlot.id);
|
||||
if (targetC?.parsedType.name === "grid_layout") {
|
||||
return (
|
||||
<div key={c.id} data-meta-ui-id={c.id} ref={ref} {...props}>
|
||||
{C}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment key={c.id}>
|
||||
{C}
|
||||
{children}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const DebugStore: React.FC = () => {
|
||||
const [store, setStore] = useState(stateStore);
|
||||
|
@ -34,7 +34,6 @@ const useHashLocation = ({ base = "" } = {}): [
|
||||
const [loc, setLoc] = useState(currentLocation(base));
|
||||
const navigate = useCallback(
|
||||
(to: string) => {
|
||||
console.log(base);
|
||||
window.location.hash = base + to;
|
||||
},
|
||||
[base]
|
||||
@ -73,7 +72,7 @@ export const RouterProvider: React.FC<{
|
||||
);
|
||||
};
|
||||
|
||||
// all route-like component must have path property, router use path to determined if a component match the route
|
||||
// all route-like component must have path property, wouter use path to determined if a component match the route
|
||||
// but we need path to match both nested router itself and its child route, so we need to have an alternative property called base as the real path of the nested router
|
||||
// and used by its children
|
||||
const NestedWouter: React.FC<{ path: string; base: string }> = ({
|
||||
@ -108,9 +107,8 @@ const NestedWouter: React.FC<{ path: string; base: string }> = ({
|
||||
|
||||
const Router: ComponentImplementation<{
|
||||
routerPolicy: Static<typeof RouterPolicyPropertySchema>;
|
||||
}> = ({ routerMap, routerPolicy, subscribeMethods }) => {
|
||||
const [, naviagte] = useLocation();
|
||||
const router = useRouter();
|
||||
}> = ({ routerMap, routerPolicy, subscribeMethods, mergeState }) => {
|
||||
const [location, naviagte] = useLocation();
|
||||
|
||||
const routes = useMemo(() => {
|
||||
let defaultPath: string | undefined = undefined;
|
||||
@ -134,7 +132,7 @@ const Router: ComponentImplementation<{
|
||||
}
|
||||
if (C.displayName === "router") {
|
||||
return (
|
||||
// it should match both itself and its children path, so we need to match its path itself
|
||||
// it should match both itself and its children path
|
||||
<NestedWouter
|
||||
path={`(${path}|${path}/.*)`}
|
||||
base={path}
|
||||
@ -146,7 +144,9 @@ const Router: ComponentImplementation<{
|
||||
}
|
||||
return (
|
||||
<Woute key={path} path={path}>
|
||||
<C key={cid}></C>
|
||||
{(params) => {
|
||||
return <C {...params} key={cid}></C>;
|
||||
}}
|
||||
</Woute>
|
||||
);
|
||||
default:
|
||||
@ -163,7 +163,8 @@ const Router: ComponentImplementation<{
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
}, [routerPolicy]);
|
||||
|
||||
useEffect(() => {
|
||||
subscribeMethods({
|
||||
navigate: (path: string) => {
|
||||
@ -171,6 +172,14 @@ const Router: ComponentImplementation<{
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// to assign location as a state
|
||||
mergeState({
|
||||
route: location,
|
||||
});
|
||||
}, [location]);
|
||||
|
||||
return <Switch children={routes}></Switch>;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user