上篇 BrowserRouter通过context的value中提供history/location/match属性,那么Route可以通过RouterContext.Consumer 获取对应的熟悉。
-
Rout主要配置项:
- path: string | string[]
- exact: bool
- component
- children: func
- render: func
在Route在都配置 children, component, render的时候,这三者是互斥的。优先级 children > component > render。
⚠️ 当为 component 时,是通过 React.createElement创建一个新的React Element 。如果为内联函数 那么每次都会产生个新的React Element(频繁的卸载组件)。
在了解优先级的情况下 看match 匹配规则部分就比较清楚了。
- props.match
- 不匹配 -- 如果存在children 并且为 children === "function" 则执行children(props),否则返回null。
- 匹配 -- 按照 children/component/render 优先级处理。
- . 如果为 children 如果存在 children 为函数的时候执行 children(props),不为函数 返回children
- . 如果为component执行 React.createElement(component, props)
- . 如果为render 执行 render(props)
- . 否则 返回 null
{props.match? children
? typeof children === "function"
?children(props)
: children
: component
? React.createElement(component, props)
: render
? render(props)
: null
: typeof children === "function"
?children(props): null}
import React from "react";
import invariant from "tiny-invariant";
import RouterContext from "./RouterContext.js";
import matchPath from "./matchPath.js";
function isEmptyChildren(children) {
return React.Children.count(children) === 0;
}
function evalChildrenDev(children, props, path) {
const value = children(props);
return value || null;
}
/**
* The public API for matching a single path and rendering.
*/
class Route extends React.Component {
render() {
return (
<RouterContext.Consumer>
{context => {
invariant(context, "You should not use <Route> outside a <Router>");
const location = this.props.location || context.location;
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;
const props = { ...context, location, match };
let { children, component, render } = this.props;
// Preact uses an empty array as children by
// default, so use null if that's the case.
if (Array.isArray(children) && isEmptyChildren(children)) {
children = null;
}
return (
<RouterContext.Provider value={props}>
{props.match
? children
? typeof children === "function"
? __DEV__
? evalChildrenDev(children, props, this.props.path)
: children(props)
: children
: component
? React.createElement(component, props)
: render
? render(props)
: null
: typeof children === "function"
? __DEV__
? evalChildrenDev(children, props, this.props.path)
: children(props)
: null}
</RouterContext.Provider>
);
}}
</RouterContext.Consumer>
);
}
}
export default Route;