: context.match;
const props = { ...context, location, match };
上述代码显示,match首先会从组件的this.props中的computedMatch属性来判断:如果this.props中存在computedMatch则直接使用定义好的computedMatch属性赋值给match,否则如果this.props.path存在,就会使用matchPath方法来根据当前的location.pathname来判断是否匹配。
然而在react router的Route组件API文档中我们似乎没有看到过有关于computedMatch的介绍,不过在源码中有一行这样的注释
// <Switch> already computed the match for us该注释说在<Switch>组件中已经为我们计算了该匹配。
接下来我们再去了解一下Switch组件:
Switch组件只会渲染第一个被location匹配到的并且作为子元素的<Route>或者<Redirect>
我们翻开Switch组件的实现源码:
let element, match; // 定义最后返回的组件元素,和match匹配变量 React.Children.forEach(this.props.children, child => {
if (match == null && React.isValidElement(child)) { // 如果match没有内容则进入该判断
element = child;
const path = child.props.path || child.props.from;
match = path // 该三元表达式只有在匹配到后会给match赋值一个对象,否则match一直为null
? matchPath(location.pathname, { ...child.props, path })
: context.match;
}
});
return match
? React.cloneElement(element, { location, computedMatch: match })
: null;
首先我们找到computedMatch属性是在React.cloneElement方法中,cloneElement方法会将追加定义的属性合并到该clone组件元素上,并返回clone后的React组件,等于就是将新的props属性传入组件并返回新组件。
在上文中找到computedMatch的值match也是根据matchPath来判断是否匹配的,matchPath是react router中的一个API,该方法会根据你传入的第一个参数pathname与第二个要匹配的props属性参数来判断是否匹配。如果匹配就返一个对象类型并包含相关的属性,否则返回null。
在React.Children.forEach循环子元素的方法中,matchPath方法判断当前pathname是否匹配,如果匹配就给定义的match变量进行赋值,所以当match被赋值以后,后续的循环就也不会再进行匹配赋值,因为Switch组件只会渲染第一次与之匹配的组件。
3. 实现一个路由缓存组件
我们知道Switch组件只会渲染第一项匹配的子组件,如果可以将匹配到的组件都渲染出来,然后只用display的block和none来切换是否显示,这也就实现了第二种解决方案。
参照Switch组件来封装一个RouteCache组件:
import React from 'react';










