1. 程式人生 > 其它 >react-router-dom入門基本使用

react-router-dom入門基本使用

技術標籤:前端之路reactrouterreact-router路由

快速入門

下載安裝

## 安裝 react 腳手架並建立專案
npm install -g create-react-app
create-react-app demo-app
cd demo-app

## 安裝 react-router-dom
## or, if you're not using yarn
## yarn add react-router-dom 
npm install react-router-dom

進入專案修改App.js

import React from 'react'
import
{ BrowserRouter as Router, Route, Link } from 'react-router-dom' const Home = () => ( <div> <h2>Home</h2> </div> ) const About = () => ( <div> <h2>About</h2> </div> ) const Topic = ({ match }) => ( <div> <h3>
{match.params.topicId}</h3> </div> ) const Topics = ({ match }) => ( <div> <h2>Topics</h2> <ul> <li> <Link to={`${match.url}/rendering`}> Rendering with React </Link> </li> <li> <
Link to={`${match.url}/components`}> Components </Link> </li> <li> <Link to={`${match.url}/props-v-state`}> Props v. State </Link> </li> </ul> <Route path={`${match.path}/:topicId`} component={Topic}/> <Route exact path={match.path} render={() => ( <h3>Please select a topic.</h3> )}/> </div> ) const App = () => ( <Router> <div> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li><Link to="/topics">Topics</Link></li> </ul> <hr/> <Route exact path="/" component={Home}/> <Route path="/about" component={About}/> <Route path="/topics" component={Topics}/> </div> </Router> ) export default App

啟動專案npm start
瀏覽器輸入:http://localhost:3000/
觀察到以下頁面表示使用router成功
在這裡插入圖片描述
可以在App.js中看到,react-router-dom中,引入了BrowserRouterRouteLink三個元件,下面開始分別介紹。

Link

使用該元件可以編寫路由路徑path,改變瀏覽器位址列的路徑,基本語法

<Link to="/">Home</Link>

to屬性:連結位置的字串表示,還可以是一個物件

<Link to={{
  pathname: '/courses',						#pathname: 表示要連結到的路徑的字串。
  search: '?sort=name',						#search: 表示查詢引數的字串形式。
  hash: '#the-hash',						#放入網址的 hash,例如 #a-hash。
  state: { fromDashboard: true }			#狀態持續到 location。
}}/>

還有一個比較常用的屬性replace,如果為 true,則單擊連結將替換歷史堆疊中的當前入口,而不是新增新入口。
react-router-dom是基於瀏覽器的history物件來進行操作的,該物件使用棧資料結構維護歷史記錄,當點選一個新的連結時,就將該連結入棧,如果replace屬性為true,點選時總是替換history物件的棧頂連結。

Route

使用該元件可以對上面Link編寫好的路由路徑進行註冊,並設定路徑對應要展示的元件。註冊的路由在進行匹配時,是從上到下按順序匹配的,若沒有Switch包裹,無論有多少個Route都進行一遍掃描匹配。
文件原話:它最基本的職責是在 location 與 Route 的 path 匹配時呈現一些 UI。

<Route exact path="/" component={Home}/>

常用屬性:
exact:如果為 true,則只有在路徑完全匹配時才匹配。預設模糊匹配,即瀏覽器地址只有前面部分完美匹配時才顯示,如瀏覽器為 /about/a/b/c,而Route為 /about,可以匹配成功,兩者反之則不行。
path:任何可以解析的有效的 URL 路徑,一般對應Link的to屬性
component:只有當位置匹配時才會渲染的 React 元件。
render:與component作用相同,該方式使用內聯編寫,而不引用外部暴露的 React 元件。render的型別是function,Route會渲染這個function的返回值。因此它的作用就是附加一些額外的邏輯
sensitive:如果路徑區分大小寫,則為 true ,則匹配。

BrowserRouter

包裹LinkRoute的元件,使得UI元件與地址URL保持同步,若LinkRoute不被BrowserRouter包裹,則會報錯。另外,Link編寫的好的路徑,在註冊時,LinkRoute必須要在同一個BrowserRouter內才會起作用,不能分開在不同的BrowserRouter。通常可以像上面的例子一樣,直接在index.js中包含<App/>元件使用。

<BrowserRouter basename={optionalString}>
  <App/>
</BrowserRouter>

basename:所有地址的基本網址。如果您的應用程式是從伺服器上的子目錄提供的,則需要將其設定為子目錄。格式正確的基本名應該有一個前導斜線,但是結尾不能有斜線。

<BrowserRouter basename="/calendar"/>
<Link to="/today"/> // renders <a href="/calendar/today">

react-router-dom還有一個元件與BrowserRouter有同樣的作用,HashRouter。與之不同,HashRouter會在路徑後面新增一個#號,如

<HashRouter basename="/calendar"/>
<Link to="/today"/> // renders <a href="#/calendar/today">

#後面的字元不會發送到後臺伺服器。


拓展NavLink

該元件也是react-router-dom裡的元件,是Link的升級版,當點選導航Link的時候,會動態給所點選的元件加類名,如

<NavLink to="/about" activeClassName="active">About</NavLink>

activeClassName:NavLink預設的加的類名就是"active",這樣當點選導航的時候就有CSS樣式顯示了


以上就是快速入門內容,現在可以學習 react-router-dom 其他的內容。

Switch

考慮以下情況:假設註冊路由時,有兩個一樣路徑會發生什麼現象?

<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/about" component={Home}/>
<Route path="/topics" component={Topics}/>

執行一下,如圖所示
在這裡插入圖片描述
可以看到,當點選About連結時,Home和About元件都顯示了出來,這是不符合實際要求的,這時就要用到了Switch元件。Route預設是全部掃描的,就算路由路徑是第一個而且已經成功匹配,還是要向下繼續掃描,使用Switch包裹Route,使得一旦路徑匹配就不繼續向下匹配了,也就是說,一個路徑只匹配一次

<Switch>
	<Route exact path="/" component={Home}/>
	<Route path="/about" component={About}/>
	<Route path="/about" component={Home}/>
	<Route path="/topics" component={Topics}/>
</Switch>

這樣下面那個 /about 路徑就不會顯示了。

Redirect

重定向,當路由沒有匹配的時候,給一個指定的路徑去匹配,to屬性指定一個路徑

<Switch>
	<Route exact path="/" component={Home}/>
	<Route path="/about" component={About}/>
	<Route path="/topics" component={Topics}/>
	<Redirect to="/somewhere/else" />
</Switch>

給路由元件傳參

前置知識:

路由元件與一般元件
    1.寫法不同:
        一般元件:<Demo/>
        路由元件:<Route path="/demo" component={Demo}/>
    2.存放位置不同:
        一般元件:components
        路由元件:pages
    3.接收到的props不同:
        一般元件:寫元件標籤時傳遞了什麼,就能收到什麼
        路由元件:接收到三個固定的屬性
                    history:
                                go: ƒ go(n)
                                goBack: ƒ goBack()
                                goForward: ƒ goForward()
                                push: ƒ push(path, state)
                                replace: ƒ replace(path, state)
                    location:
                                pathname: "/about"
                                search: ""
                                state: undefined
                    match:
                                params: {}
                                path: "/about"
                                url: "/about"

假設要給About元件傳遞一個id引數
方法1:通過傳遞params引數,瀏覽器位址列變為 /about/01

## 傳參
const id = '01';
const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to={`/about/${id}`}>About</Link></li>
      </ul>
      <hr/>
      <Route path="/about/:id" component={About}/>
    </div>
  </Router>
)

## About元件中接收引數 
const { id } = this.props.match.params;
## 在傳遞時,react預設將引數整理成一個物件
{ id:'01',... }

如有多個引數,只需要繼續在Link的to屬性後加/接著拼寫就行,Route那裡同理。

方法2:通過傳遞search引數,這將顯示在位址列上的urlencoded字串,需要藉助 react 內建的庫querystring解析該引數為JSON物件

## 傳參
const id = '01';
const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to={`/about/?id=${id}`}>About</Link></li>
      </ul>
      <hr/>
      ## search傳遞引數不需要改動 Route
      <Route path="/about" component={About}/>
    </div>
  </Router>
)

## About元件中接收引數 
import qs from 'querystring'
...
const {search} = this.props.location
const { id } = qs.parse(search.slice(1)) ## 截去第一個問號 ?

## 拓展 querystring 另外一個方法 stringify() 可以將JSON物件轉換為如下形式
qs.stringify({id:'01',title:'zlfan'}) ---> "id=01&title=zlfan"

方法3:通過傳遞state引數,該方法在位址列不會有任何顯示,但是重新整理瀏覽器仍然保留住引數state

## 傳參
const id = '01';
const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to={{pathname:'/about',state:{id:'01'}}}>About</Link></li>
      </ul>
      <hr/>
      ## state傳遞引數不需要改動 Route
      <Route path="/about" component={About}/>
    </div>
  </Router>
)

## About元件中接收引數 
const { id } = this.props.location.state;

withRouter

可以通過 withRouter 高階元件訪問 history 物件的屬性和最近的 的 match 。 當路由渲染時, withRouter 會將已經更新的 match , location 和 history 屬性傳遞給被包裹的元件。
將一般元件變成路由元件,即元件props能接收到historylocationmatch三個引數

import React from 'react'
import { withRouter } from 'react-router'
class ShowTheLocation extends React.Component {
	....
}

export default withRouter(ShowTheLocation)

參考:

https://www.bilibili.com/video/BV1wy4y1D7JT?p=77
https://react-router.docschina.org/web/guides/philosophy
https://www.jianshu.com/p/6583b7258e78