目录
- 1,原生 Switch 的渲染内容
- 2,实现
1,原生 Switch 的渲染内容
对如下代码来说:
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
function News() {return <div className="page news">News</div>;
}function Goods() {return <div className="page goods">Goods</div>;
}export default function App() {return (<Router><Switch><Route path="/page1" component={News}></Route><Route path="/page2" component={Goods}></Route></Switch></Router>);
}
React 插件展示的内容:
可以看到,除了也使用了 Router 的上下文之外,只加载了一个 Route 组件。
2,实现
经测试,Switch
的子元素有如下规则:
- 如果不是
Route
组件,则会报错。 - 如果只有一个
Route
组件,则得到的props.children
的类型是对象。 - 如果有多个
Route
组件,则得到的props.children
的类型是数组。
所以,除了做以上特殊的判断外,再加上渲染第一个匹配到的组件的逻辑即可。
import React, { Component } from "react";
import ctx from "./RouterContext";
import { Route } from "./Route";
import matchPath from "./matchPath";export class Switch extends Component {getChildren = ({ location }) => {let children = [];if (Array.isArray(this.props.children)) {children = this.props.children;} else if (typeof this.props.children === "object") {children = [this.props.children];}for (const child of children) {if (child.type !== Route) {throw new TypeError("子元素非 Route 组件");}const { path = "/", exact = false, strict = false, sensitive = false } = child.props;const result = matchPath(path, location.pathname, {exact,strict,sensitive,});if (result) {return child;}}return null;};render() {return <ctx.Consumer>{this.getChildren}</ctx.Consumer>;}
}
注意到,判断是否是 Route
组件,可通过引入的 Route
组件直接进行判断。
以上。