1、Router组件
1.1 属性
| children | 结点 |
history | 必传对象 |
staticContext | 对象 |
router作为context的提供者。其有两层context
render() { return ( <RouterContext.Provider value={{ history: this.props.history, location: this.state.location, match: Router.computeRootMatch(this.state.location.pathname), staticContext: this.props.staticContext }} > <HistoryContext.Provider children={this.props.children || null} value={this.props.history} /> </RouterContext.Provider> ); } }BrowserRouter和HashRouter基本骨架是一样的,除了history属性,BrowserRouter的history是通过createBrowserHistory创建,而HashRouter的history是通过createHashHistory创建
路由提供者的对象成员有
history,其也会作为history的提供值
action: Action location: Location createHref(to: To): string push(to: To, state?: any): void replace(to: To, state?: any): void go(delta: number): void back(): void forward(): void isten(listener: Listener): () => void block(blocker: Blocker): () => voidlocation
match
staticContext
1.2 路由对象
StaticRouter:用在服务端渲染
其属性有
| 属性名 | 说明 |
| basename | 路由的前缀名 |
context | 上下文信息 |
location | url信息 |
2、Route组件
2.1 属性
| children | 函数或者结点 |
| exact | 布尔类型 |
| location | 对象 |
| path | 字符串或者字符串数组 |
| render | 函数 |
| sensitive | 布尔值 |
| strict | 布尔值 |
| component | 组件 |
children和component同时配置时,component会被忽略
children和render同时配置时,render会被忽略
route组件中基于router的context以及route组件的属性来构造给路由对应组件的消费的属性,其中包含context,location,match。其中match计算返回的一个包含以下属性的对象
| 参数 | 说明 |
path | 路径 |
url | url的匹配部分 |
isExact | 是否精确匹配 |
params | 模板参数 |
const match = this.props.computedMatch ? this.props.computedMatch // <Switch> already computed the match for us : this.props.path ? matchPath(location.pathname, this.props) : context.match; function matchPath(pathname, options = {}) { if (typeof options === "string" || Array.isArray(options)) { options = { path: options }; } const { path, exact = false, strict = false, sensitive = false } = options; const paths = [].concat(path); return paths.reduce((matched, path) => { if (!path && path !== "") return null; if (matched) return matched; const { regexp, keys } = compilePath(path, { end: exact, strict, sensitive }); const match = regexp.exec(pathname); if (!match) return null; const [url, ...values] = match; const isExact = pathname === url; if (exact && !isExact) return null; return { path, // the path used to match url: path === "/" && url === "" ? "/" : url, // the matched portion of the URL isExact, // whether or not we matched exactly params: keys.reduce((memo, key, index) => { memo[key.name] = values[index]; return memo; }, {}) }; }, null); }其计算匹配依赖path-to-regexp库
2.2 element和component区别
element是react router v6的写法
component是react router v5以及之前的写法
<Route path="/" component={Home} /> //v5 <Route path="/" element={<Home />} /> //v63、Switch组件
作为Router的context的消费者,在子结点中找到匹配路径的route返回
class Switch extends React.Component { render() { return ( <RouterContext.Consumer> {context => { invariant(context, "You should not use <Switch> outside a <Router>"); const location = this.props.location || context.location; let element, match; // We use React.Children.forEach instead of React.Children.toArray().find() // here because toArray adds keys to all child elements and we do not want // to trigger an unmount/remount for two <Route>s that render the same // component at different URLs. React.Children.forEach(this.props.children, child => { if (match == null && React.isValidElement(child)) { element = child; const path = child.props.path || child.props.from; match = path ? matchPath(location.pathname, { ...child.props, path }) : context.match; } }); return match ? React.cloneElement(element, { location, computedMatch: match }) : null; }} </RouterContext.Consumer> ); } }