官网 中文官网
vue-router和react-router的区别:
vue-router | react-router |
---|---|
分离式 | 嵌套式 |
排他性(只有一个路由被渲染) | 包容性(多路由渲染) |
静态路由 | 动态路由 |
安装
React Router被拆分成三个包:
react-router
react-router-dom
react-router-native
结构
BrowserRouter|HashRouter
BrowserRouter
import React from 'react';
import ReactDom,{render} from 'react-dom';
import {BrowserRouter, HashRouter, Route} from 'react-router-dom'
import Default from "./layouts/Default";
render(
<BrowserRouter>
<Route component={Default}/>
</BrowserRouter>,
document.getElementById('root')
);
Route
path:(string object)路由匹配路径。没有path属性的Route总是会匹配。
exact:(boolean)为true时,全局匹配(/home),多个Route可以同时匹配和渲染。
component:(function)匹配地址的时候React的组件才回被渲染。
<Route path="/home" component={Home}/>
Link
to:(string) | {pathname,search,hash}要跳转的路径或地址
replace:(boolean) 是否替换历史记录
let {history,location,match}=props
<Link to={match.url+'/001'}/>
<Link to={`${match.url}/002?a=1&b=2`}/>
<Link to={{pathname:match.url+'/003',search:'?a=11&b=12',hash:'#a1'}}
NavLink
to:(string object)跳转的路径或地址
replace:(boolean) 是否替换历史记录
activeClassNamestring:当元素被选中时,设置选中样式,默认为active
activeStyle:(object)当元素被选中时,设置选中样式
exact:(Boolean)严格匹配
<NavLink activeClassName="default__nav--active" to="/home">首页</NavLink>
Switch
该组件用来渲染匹配地址的第一个Route或者Redirect,仅渲染一个路由,排他性路由,默认全匹配 (场景:侧边栏和面包屑,引导选项卡等
location:(string object)
children:(node)
Redirect
from:(string) 来自
to:(string object) 去向
push:(boolean) 添加历史记录
exact:(boolean) 严格模式
sensitive:(boolean) 区分大小写
参数数据传递
<Switch>
<Redirect from="/" to="/home"/>
</Switch>
404
<Route component={NoPage}/> //总是会匹配
编程式跳转
history.push('/user?a=1&b=2')
history.push({pathname:'/user',search:'?a=11&b=22'})
history.replace({pathname:'/user',search:'?a=111&b=222'})
history.go(-1)
例子
import React from 'react';
export default class Home extends React.Component{
render(){
return (
<div className="home">
<h3>首页</h3>
<button onClick={()=>this.props.history.push('/login')}>跳转</button>
<button onClick={()=>this.props.history.push({pathname:'/goods/4',search:'a=3&b=4'})}>跳转2</button>
</div>
)
}
}
非路由跳转组件
不是所有组件会通过路由跳转,也需要抓取路由上下文时,解决方案
import {withRouter} from 'react-router-dom'
class App extends Component{}
export default withRouter(App)
例子
import React from 'react';
import {withRouter} from 'react-router-dom';
class Child extends React.Component {
render() {
return (
<div className="Child">
<h3>Child</h3>
</div>
)
}
}
export default withRouter(Child)
前置授权路由
需要自定义路由,具体为,自定义一个组件,代替Route,其内部根据条件返回一个Route 组件指向目标组件,或者Route的render函数内部判断加载目标,最后组件树关系为:switch>自定义组件>Route>目标组件
<Auth path="/goods" component={Goods} />
<Auth path="/user" component={User} />
export default class Auth extends React.Component{
state={
hasSendAuth:false,
auth:false,
data:{}
};
async componentDidMount(){
let res = await axios({url:'/data/user.json'})
console.log('数据回来了')
this.setState({
auth:res.data.auth,
hasSendAuth:true,
data:res.data.data
})
}
render(){
// console.log('渲染了',this.props) //包含了path,component的一个传入
let {component:Component} = this.props;//目标组件
if (!this.state.hasSendAuth) return null;
return <Route render={props=>(//...props 目标组件需要用到的路由信息
this.state.auth ?
<Component {...props} data={this.state.data} /> :// 数据预载
<Redirect to="/login" />
)}/>
}
}
后置守卫
// reg.jsx
import { Prompt } from 'react-router-dom'
<Prompt
when={this.state.isBlocking}
message={location=>...}
/>
message: 后面可以跟简单的提示语,也可以跟函数,函数是有默认参数的。
when: when的属性值为true时防止跳转;