react-router > 4.0 路由

一、如何找到文檔

在 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ù)主要包含四部分:

  1. history里面有push
  2. location 有query(search)和params(state)
location內(nèi)容
{
    hash: ""
    pathname: "/about"
    search: ""
    state: {id: 10}
}
  1. match配置路由路徑
  2. 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。

  1. useHistory
import { useHistory } from "react-router-dom";
const history = useHistory();
history.push({pathname:"/index"})
  1. useParams

useParams返回URL參數(shù)的鍵/值對的對象。使用它來訪問match.params當前<Route>,所以只對:

<Route path="/about/:slug" component={A} ></Route>

組件有效,push 或 params 攜帶參數(shù)都不行。

  1. useLocation

該useLocation掛鉤返回location代表當前URL 的對象。

重點:配合 useEffect 可作為局部組件守衛(wèi)使用。

  1. 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

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。