目录
- 1,原生 Route 的渲染内容
- 2,实现
1,原生 Route 的渲染内容
对如下代码来说:
import { BrowserRouter as Router, Route } from "react-router-dom";
function News() {
return <div>News</div>;
}
function Goods() {
return <div>Goods</div>;
}
export default function App() {
return (
<Router>
<Route path="/page1" component={News}></Route>
<Route path="/page2" component={Goods}></Route>
</Router>
);
}
React 插件展示的内容:
可以看到每个 Route
组件中,还会有一个 Router 上下文。
这是因为,每个 Route
组件匹配的 match
对象不同,所以得再提供一次。除此之外,history
和 location
这2个对象并没有发生变化。
2,实现
import React, { Component } from "react";
import ctx from "./RouterContext";
import matchPath from "./matchPath";
export class Route extends Component {
renderChildren = (ctx) => {
const { children, render, component } = this.props;
// children 无论是否匹配都会渲染,也可以是函数,
if (children !== undefined && children !== null) {
if (typeof children === "function") {
return children(ctx);
} else {
return children;
}
}
// 没有匹配到路径,同时 children 没有内容
if (!ctx.match) {
return null;
}
// render 属性
if (typeof render === "function") {
return render(ctx);
}
// 只有 component 属性有值
if (component) {
const Comp = component;
return <Comp {...ctx}></Comp>;
}
return null;
};
matchRoute = (pathname) => {
const { path, exact = false, strict = false, sensitive = false } = this.props;
return matchPath(path || "/", pathname, {
exact,
strict,
sensitive,
});
};
/**
* 上下文消费者函数
* Route 组件中又会提供一个 Router 的上下文,
* history 和 location 对象相同,match 对象会重新进行匹配。
*/
consumerFunc = (value) => {
// 上下文对象定义在这里,当 Router 组件传递的上下文内容发生变化时,也会实时更新。
const ctxValue = {
history: value.location,
location: value.location,
match: this.matchRoute(value.location.pathname),
};
return <ctx.Provider value={ctxValue}>{this.renderChildren(ctxValue)}</ctx.Provider>;
};
render() {
return <ctx.Consumer>{this.consumerFunc}</ctx.Consumer>;
}
}
以上代码经过测试,和原生 Route
组件表现一致。
以上。