router
constructor(props) {
super(props)
this.state = {
// history会计算出当前的path等信息,保存在location属性上,作为 <Router /> 的props
location: props.history.location
};
componentDidMount() {
this.unlisten = props.history.listen(location => {
this.setState({ location }) // 触发应用的更新
})
}
render() {
return (
// 给 route 用
<RouterContext.Provider
value={{
history: this.props.history,
location: this.state.location,
match: Router.computeRootMatch(this.state.location.pathname),
}}
>
{this.props.children || null}
</RouterContext.Provider>
)
}
}
route
class Route extends React.Component {
render() {
return (
<RouterContext.Consumer>
{
context => {
const location = context.location; // 路由相关
const match = this.props.path // 是否匹配当前url
? matchPath(location.pathname, this.props)
: context.match;
const props = { ...context, location, match }
let { children, component, render } = this.props
// children不能有多个
if (Array.isArray(children) && children.length === 0) children = null;
return (
// 我理解是给 withRouter 等这种高阶组件获取history的
<RouterContext.Provider value={props}>
// 如果 path 匹配上了, 渲染children
{props.match
? children
? typeof children === "function"
? children(props)
: children
// 然后是 component
: component
? React.createElement(component, props)
// render
: render
? render(props)
: null
: typeof children === "function"
? children(props)
: null}
</RouterContext.Provider>
// 1. 渲染的优先级是 children > component > render;
// 2. 如果没有匹配上path, children如果是function,那么也会渲染出来;
)
}}
</RouterContext.Consumer>
);
}
}