分支渲染
- 当通过
matchRouteBranch 得到匹配的branches之后, 即可通过 _renderMatches 来得到需要渲染的element以及对嵌套路由的处理.
Outlet: 消费者
<Outlet> 用于渲染嵌套的子路由 , 功能类似于 vue-router 中的 <router-view>
export function Outlet(props: OutletProps): React.ReactElement | null {
return useOutlet(props.context);
}
useOutlet
export function useOutlet(context?: unknown): React.ReactElement | null {
let outlet = React.useContext(RouteContext).outlet;
if (outlet) {
return (
<OutletContext.Provider value={context}>{outlet}</OutletContext.Provider>
);
}
return outlet;
}
renderMatches: 提供者
- 将
branches 转换成 渲染的 element
- 每次的累加结果都将作为下次循环中的
outlet
- children渲染的element,可以使用
<Outlet> 来消费 <RouteContext.Provider>提供的outlet(其实就是渲染嵌套的子路由)
export function _renderMatches(
matches: RouteMatch[] | null,
parentMatches: RouteMatch[] = []
): React.ReactElement | null {
if (matches == null) return null;
return matches.reduceRight((outlet, match, index) => {
return (
<RouteContext.Provider
children={
match.route.element !== undefined ? match.route.element : outlet
}
value={{
outlet,
matches: parentMatches.concat(matches.slice(0, index + 1)),
}}
/>
);
}, null as React.ReactElement | null);
}
一个🌰
parent 路径下存在两个子路由(sub1和sub2)
function App(){
return <Routes>
<Route path="/parent" element={<Parent />}>
<Route path="sub1" element={React.createElement('h1',{},'sub1')}></Route>
<Route path="sub2" element={React.createElement('h1',{},'sub2')}></Route>
</Route>
</Routes>
}
function Parent() {
return (
<div>
<h2>Parent</h2>
<Outlet/>
</div>
);
}
- 通过
matchRouteBranch 匹配的branches如下
parent -> parent/sub1
- 浏览器中地址栏如下
http:
renderMatches 过程描述
match.route.element : sub1对应的element(即这里渲染sub1的h1元素)
outlet: null
matches和parentMatches : [parent的branch,sub1的branch]
<RouteContext.Provider
value={{
outlet:null,
matches: [parent的branch,sub1的branch],
}}
>
{sub1}
</RouteContext.Provider>
match.route.element : Parent组件对应的element
outlet: 上一轮的结果 temp1
matches和parentMatches : [parent的branch]
<RouteContext.Provider
value={{
outlet: <RouteContext.Provider
children={sub1}
value={{
outlet:null,
matches: [parent的branch,sub1的branch],
}}
/>
matches: [parent的branch],
}}
>
{Parent}
</RouteContext.Provider>
<Parent> 中会消费 RouteContext(即这里得到的 temp1), 所以 sub1 就通过在<Parent>中的 <Outlet>进行了显示
其他
- reduceRight中的 index 参数是倒序的