路由
官網 中文官網
vue-router和react-router的區別:
vue-router | react-router |
---|---|
分離式 | 嵌套式 |
排他性(只有一個路由被渲染) | 包容性(多路由渲染) |
靜態路由 | 動態路由 |
安裝
React Router被拆分成三個包:
react-router
react-router-dom
react-router-native
結構
BrowserRouter|HashRouter
- 根組件(App)
- NavLink|Link
- Route
- Redirect
- 子組件
- NavLink|Link
- Route
- …
- 子組件
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>
)
}
}
非路由跳轉組件
不是所有組件會通過路由跳轉,也需要抓取路由上下文時,解決方案
- 通過路由跳轉
- 通過屬性傳遞
- 通過withRouter包裝
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時防止跳轉;