一、如何找到文檔
在 GitHub 上直接搜索 react-router 進入,就能找到開發(fā)文檔,
這里可以提供下,鏈接:https://reacttraining.com/react-router/
現(xiàn)在路由都是使用 react-router-dom 了。
二、路由容器
這個和以前 3.0 版本的路由配置不一樣了,現(xiàn)在路由對應兩種模式提供兩個路由容器。
- hashhistory
import { HashRouter as Router } from "react-router-dom";
- browerhistory
import { BrowserRouter as Router } from "react-router-dom";
Vue 就一個路由容器 <router-view />
三、如何放置路由
react-router-dom 書寫的路由方式是聲明式,可以說是非常的難用,所以一般都是封裝成類似 vue-router 路由書寫方式。
<Router>
<div>
<Route path="/" render={() => <Child component={App} />} ></Route>
<Route path="/" component={A} ></Route>
<Route path="/" children={()=><A/>} ></Route>
children為函數(shù)時不管path匹不匹配都會顯示組件,如果不是函數(shù)顯示效果和component相同
</div>
</Router>
路由書寫優(yōu)先級為 component > render > children
四、路由跳轉(zhuǎn)和傳參
類似 Vue 中的 this.$router,react 路由參數(shù)主要包含四部分:
- history里面有push
- location 有query(search)和params(state)
location內(nèi)容
{
hash: ""
pathname: "/about"
search: ""
state: {id: 10}
}
- match配置路由路徑
- staticContext
路由跳轉(zhuǎn)的兩種方式:
- 聲明式
<Link to="/about?user=CondorHero">關于</Link>
<Link to={{pathname:"/about",search:"CondorHero"}}>關于</Link>
<Link to={{pathname:"/about",state:{id:10}}}>關于</Link>
比較特殊的還有一個 NavLink 導航鏈接,不同于 Link ,NavLink 可以增加樣式。常用于單頁面左側(cè)導航。
<NavLink to="/about" style={{fontWeight: "bold",color: "red"}}>About</NavLink>
<NavLink to="/about" activeClassName="className">About</NavLink>
元素處于活動狀態(tài)時應用于元素的樣式, 可以行內(nèi)也可以類名添加活動樣式。
- 編程式
push方法,兩種配置方式能夠 push ,一種是 <Route></Route> 包裹的組件,通過 this.props.history.push
另一種是通過,history 模塊,或者是 useHistory 鉤子。
五、重定向
新位置將覆蓋歷史記錄堆棧中的當前位置,就像服務器端重定向(HTTP 3xx)一樣。
import { Redirect } from "react-router-dom";
<Redirect to="/somewhere/else" />
//用法和Link一樣
六、如何在任意組件找到 Vue this 上的路由對象
Vue 2.0 的路由是綁定在 this 的身上,React 路由只會出現(xiàn)在 和 <Route></Route>
綁定的組件內(nèi)部,所以其他組件要想跳轉(zhuǎn)路由并傳參的話,兩種辦法。
- history
注意??這個 history 不是瀏覽器原生的。
import { createBrowserHistory , createHashHistory } from "history";
const customHistory = createBrowserHistory();
console.log(customHistory)
- withRouter
import { withRouter } from "react-router-dom";
function Main(props){
console.log(props)
return (
<div>
<h1>你好</h1>
</div>
)
}
const A = withRouter(Main);
/*A仍然作為組件使用*/
<A></A>
七、路由鉤子
這個路由鉤子不是路由守衛(wèi),React-router 腦殘,在 4.0 把路由攔截給刪了,這里出現(xiàn)的路由鉤子完全是針對 react-hook而言的路由hooks。react 版本要求大于 16.8。
- useHistory
import { useHistory } from "react-router-dom";
const history = useHistory();
history.push({pathname:"/index"})
- useParams
useParams返回URL參數(shù)的鍵/值對的對象。使用它來訪問match.params當前<Route>,所以只對:
<Route path="/about/:slug" component={A} ></Route>
組件有效,push 或 params 攜帶參數(shù)都不行。
- useLocation
該useLocation掛鉤返回location代表當前URL 的對象。
重點:配合 useEffect 可作為局部組件守衛(wèi)使用。
- useRouteMatch
八、回到頂部
:root{
scroll-behavior:smooth;
}
window.scrollTo(0,0);
九、路由精確匹配問題
react 路由默認是模糊匹配,例如:
<Route path="/" render={() => <B />} ></Route>
<Route path="/index" render={() => <index />} ></Route>
<Route path="/:user" render={() => <User />} ></Route>
輸入 index 三個路徑都會匹配。路由添加 exact(精確)屬性可以精確匹配。必須是路徑和大小寫一樣。
還有一個組件是 switch ,組件內(nèi)部采用模糊匹配,但是只會匹配一個路由。
<Switch>
<Route path="/" exact render={() => <B />} ></Route>
<Route path="/index" render={() => <index />} ></Route>
<Route path="/:user" render={() => <User />} ></Route>
</Switch>
十、靜態(tài)化路由
相信你也發(fā)現(xiàn)了,嵌套路由寫起來麻煩維護起來也麻煩。就沒有類似 vue-router 那樣數(shù)組的寫法嗎。還真沒有需要自己來實現(xiàn)。但是官方也維護一個未來版 react-router-config 。不過實在是太簡陋了。
一個簡單的用法示例:
相對 Vue-Router 來講:
- 這個routes就相當于children
- {renderRoutes(this.props.route.routes)} 就相當于 router-view
class B extends React.Component {
constructor(props) {
super(props);
this.route = this.props.route;
}
render() {
return (
<div>
<h1>B</h1>
{renderRoutes(this.route.routes)}
</div>
)
}
}
class Root extends React.Component {
constructor(props) {
super(props);
this.route = this.props.route;
}
render() {
return (
<div>
<h1>我是Root組件</h1>
{renderRoutes(this.route.routes)}
<h1>我是Root組件</h1>
</div>
)
}
}
class Index extends React.Component {
constructor(props) {
super(props);
this.route = this.props.route;
}
render() {
return (
<div>
<h2>我是Index組件</h2>
{renderRoutes(this.props.route.routes,{ someProp: "these extra props are optional" })}
</div>
)
}
}
class Child extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>我是child組件</h3>
{renderRoutes(this.props.route.routes,{ someProp: "these extra props are optional" })}
<h3>我是child組件</h3>
</div>
)
}
}
const routes = [
{
component: Root,
routes: [
{
path: "/",
exact: true,
component: Index
},
{
path:"/B",
component:B,
routes: [
{
path: "/B/child",
component: Child
}
]
}
]
}
];
ReactDOM.render(
<React.StrictMode>
<Router>
<div>
{renderRoutes(routes)}
</div>
</Router>
</React.StrictMode>,
document.getElementById('root')
);
十一、路由即組件
react-router < 4.0
的時候,路由可以嵌套使用,現(xiàn)在已經(jīng)不支持了:
<Router history={history}>
<Route path="/" components={App}>//App組件里面有this.props.children
<Route path="haha" component={Haha}></Route>
<Route path="xixi" component={Xixi}></Route>
</Route>
</Router>
用 Vue 的話講就是:以前 this.props.children 是 router-view ,現(xiàn)在 Route 是 router-view
最后
還有一個知識點:PureComponent 和 Component 的區(qū)別?
PureComponent 只會在 state 和 props 不同才會更新。
參考:React 的 PureComponent Vs Component
當前時間 2020年5月5日 星期二 13:22:52