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中,引入了BrowserRouter
,Route
,Link
三個元件,下面開始分別介紹。
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
包裹Link
和Route
的元件,使得UI元件與地址URL保持同步,若Link
和Route
不被BrowserRouter
包裹,則會報錯。另外,Link
編寫的好的路徑,在註冊時,Link
和Route
必須要在同一個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能接收到history
,location
,match
三個引數
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