
1、Router组件1.1 属性children结点history必传对象staticContext对象router作为context的提供者。其有两层contextrender() { 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): () voidlocationmatchstaticContext1.2 路由对象StaticRouter用在服务端渲染其属性有属性名说明basename路由的前缀名context上下文信息locationurl信息2、Route组件2.1 属性children函数或者结点exact布尔类型location对象path字符串或者字符串数组render函数sensitive布尔值strict布尔值component组件children和component同时配置时component会被忽略children和render同时配置时render会被忽略route组件中基于router的context以及route组件的属性来构造给路由对应组件的消费的属性其中包含contextlocationmatch。其中match计算返回的一个包含以下属性的对象参数说明path路径urlurl的匹配部分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 Routes 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 ); } }