语法分析(react-router-dom)
一、安装react-router-dom
npm install react-router-dom --save-dev
二、在根组件上配置路由,引用react-router-dom结构{ HashRouter as Router, Route ,Link ,Redirect ,Switch },HashRouter组件是路由的根组件,定义属性和方法传递给子组件。Router组件进行路由,指定每个路由跳转到相应的组件。Link组件指定跳转链接。Redirect组件路由重定向,不管什么情况下,都会跳转当前指定的路径,和switch组件联合起来一起调用,当路径匹配到路由,不在往下匹配。
import React from 'react';
import './App.css';
import { HashRouter as Router, Route ,Link ,Redirect ,Switch } from './react-router-dom'
import Home from "./view/Home";
import Profile from "./view/Profile";
import Detail from "./view/Detail";
function App() {
return (
<div className="App">
<Router>
<div>
<div>
<Link to="/">首页</Link>
<Link to="/profile">主页</Link>
<Link to="/detail">详情页</Link>
</div>
<div>
<Switch>
<Route path="/home" exact component={Home}></Route>
<Route path="/profile" exact component={Profile}></Route>
<Route path="/detail" exact component={Detail}></Route>
<Redirect to="/home"></Redirect>
</Switch>
</div>
</div>
</Router>
</div>
);
}
export default App;
实现react-router-dom
一、首先了解HashRouter和HistoryRouter的区别,HashRouter是根据路径"#"后面参数进行匹配路由,在服务器上匹配的路径,始终只有一个。HistoryRouter是根据"/"后面的参数匹配路由,在服务器上会匹配多个路由地址,在服务器上并不会存在这些地址,报错404。
二、HashRouter定义状态,状态存储默认pathname哈希值和push方法路由跳转。
componentDidMount(){
let _that = this;
window.location.hash = window.location.hash || "/";
window.addEventListener("hashchange",function(){
_that.setState({
..._that.state,
location:{
..._that.state.location,
pathname: window.location.hash.slice(1) || "/"
}
})
})
}
三、HashRouter根组件上状态传递给子组件,用到react16的新属性React.createContext()
import React from 'react';
let {Provider ,Consumer} = React.createContext();
export {Provider ,Consumer};
四、Route组件进行路由匹配,匹配到哪个组件,进行渲染,pathToRegexp模块可以匹配链接地址的多个层级。
render(){
let {path ,component:Component} = this.props;
return <Consumer>
{(state)=>{
let exact = this.props.exact || false;
let reg = pathToRegexp(path,[],{end:exact});
let {pathname} = state.location;
if(reg.test(pathname)){
return <Component {...state}></Component>;
}
return null;
}}
</Consumer>
}
五、Link和Redirect组件指定元素的click事件,调用根组件push方法跳转。
render(){
return <Consumer>
{(state)=>{
return <a onClick={()=>state.history.push(this.props.to)}>
{this.props.children}
</a>
}}
</Consumer>
}
六、Switch组件遍历子组件的pathname是否等于地址栏的哈希值,只有相等,才返回当前组件,Redirect组件除外。
render(){
return <Consumer>
{(state)=>{
let exact = false;
let pathname = state.location.pathname;
let children = this.props.children
for(var i=0;i<children.length;i++){
let child = children[i];
let path = child.props.path || '';
let reg = pathToRegexp(path,[],{end:exact});
if(reg.test(pathname)){
return child;
}
};
return null;
}}
</Consumer>
}
网友评论