新建Router.js
import React,{Component} from 'react';
//创建Context
const RouterContext=React.createContext()
//创建Router
class Router extends Component{
constructor(props){
super(props);
//state提供更新historypath的方法
this.state={
path:'/',
updateHistoryPath:this.updateHistoryPath,
router:this
};
}
updateHistoryPath(path){
window.history.pushState(path,`title-${path}`,path)
this.setState((state)=>{
return {
path:path
}
});
}
componetDidMount(){
}
componentWillUnmount(){
}
renderChildren(){
return this.props.children.map((children)=>{
return children
})
}
render(){
return (
<RouterContext.Provider value={this.state}>
{this.renderChildren()}
</RouterContext.Provider>
)
}
}
//创建Link class Link extends Component{
constructor(props){
super(props);
}
//render函数中消费Context
render(){
return (
<RouterContext.Consumer>
{
({updateHistoryPath,router})=>
(
<a className="link" href="javascript:void(0)" onClick={(e)=>updateHistoryPath.call(router,this.props.to)}> {this.props.children}</a>
)
}
</RouterContext.Consumer>
)
}
}
//创建Route
class Route extends Component{
constructor(props){
super(props);
this.state={};
}
//render函数中消费Context,根据path进行匹配
render(){
const RenderComponent = this.props.component ;
return (
<RouterContext.Consumer>
{
({path})=>{
if(path === this.props.path){
return <RenderComponent/>
}else{
return <></>
}
}
}
</RouterContext.Consumer>
)
}
}
export default Router;
export {Link,Route}
使用Router,新建App.js
import React,{Component} from 'react'
import Router,{Link,Route} from './router/Router'
class Home extends Component{
render() {
return <h3>Home</h3>
}
}
class About extends Component{
render() {
return <h3>About</h3>
}
}
class List extends Component{
render() {
return(
<React.Fragment>
<h3></h3>
<ul>
<li>
<Link to="/list">列表</Link>
</li>
</ul>
<div>
<Route path="/list" component={ListIndex}></Route>
<Route path="/list/detail" component={ListDetail}></Route>
</div>
</React.Fragment>
)
}
}
class ListIndex extends Component{
render(){
let items=[
{
name:'张三',
id:"zs"
},
{
name:'李四',
id:"ls"
}
];
return (
<div>
{
items.map((item)=><p key={item.id}><Link to={`/list/detail/${item.id}`}>{item.name}</Link></p>)
}
</div>
)
}
}
class ListDetail extends Component{
render(){
console.log(this);
return(
<div>
<p>www</p>
</div>
)
}
}
class App extends Component{
render() {
return (
<div>
<h1>欢迎回来,菜单如下:</h1>
<Router>
<ul>
<li>
<Link to="/">HOME</Link>
</li>
<li>
<Link to="/about">ABOUT</Link>
</li>
<li>
<Link to="/list">LIST</Link>
</li>
</ul>
<h3>主体内容:</h3>
<div>
<Route path="/" component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/list" component={List}></Route>
</div>
</Router>
</div>
</div>
)
}
}
export default App;
为什么要用Context
Router作为父组件,维护了path,并提供更新path的方法updateHistoryPath 子组件Link需要调用updateHistoryPath,Link作为子组件是通过父组件调用this.props.children 因此无法传递updateHistoryPath,这种情况使用Context作为状态传递