React List - React Router

Create by jsliang on 2019-04-26 13:13:18
Recently revised in 2019-04-29 15:25:01php

Hello 小夥伴們,若是以爲本文還不錯,記得給個 star , 小夥伴們的 star 是我持續更新的動力!GitHub 地址html


【2019-08-16】Hello 小夥伴們,因爲 jsliang 對文檔庫進行了重構,這篇文章中的一些連接可能失效,而 jsliang 缺少精力維護掘金這邊的舊文章,對此深感抱歉。請須要獲取最新文章的小夥伴,點擊上面的 GitHub 地址,去文檔庫查看調整後的文章。前端


一 目錄

不折騰的前端,和鹹魚有什麼區別react

目錄
一 目錄
二 前言
三 初試
四 簡介
五 BrowserRouter
5.1 BrowserRouter 語法
5.2 BrowserRouter - basename
5.3 BrowserRouter - getUserConfirmation
5.4 BrowserRouter - forceRefresh
5.5 BrowserRouter - keyLength
六 HashRouter
6.1 HashRouter - basename
6.2 HashRouter - getUserConfirmation
6.3 HashRouter - hashType
七 Link
7.1 Link - to
7.2 Link - replace
7.3 Link - other
八 NavLink
8.1 NavLink - activeClassName
8.2 NavLink - activeStyle
8.3 NavLink - exact
8.4 NavLink - isActive
九 MemoryRouter
9.1 MemoryRouter - initialEntries
9.2 MemoryRouter - initialIndex
9.3 MemoryRouter - getUserConfirmation
9.4 MemoryRouter - keyLength
十 Redirect
10.1 Redirect - from
10.2 Redirect - to
10.3 Redirect - push
10.4 Redirect - exact
十一 Route
11.1 Route - component
11.2 Route - render
11.3 Route - children
11.4 Route - path
11.5 Route - exact
11.6 Route - location
11.7 Route - sensitive
十二 Switch
十三 篇外一:history
十四 篇外二:Code Splitting
十五 篇外三:Scroll To Top
15.1 跳轉頁面後滾動到頂部
15.2 頁面滾動到頂部
十六 篇外四:Redux
十七 總結

二 前言

返回目錄git

前端路由,是指改變 URL 路徑的形式,從而切換到不一樣的頁面,例如:github

  • localhost:3000/home
  • localhost:3000/user

經過切換不一樣的 URL,顯示不一樣的頁面,從而有了 路由 的概念。web

這篇文章咱們講解在 React 中如何經過 React Router 這個插件,靈活使用路由。ajax

jsliang 瞎吹的,最好本身百度 前端路由 是啥。npm

  • 參考資料:
  1. React Router 官方文檔
  2. React Router 中文文檔
  3. React Router 中文文檔(舊)
  4. React Router DOM 中文文檔(一) - 簡書
  5. React Router DOM 中文文檔(二) - 簡書
  • 篇外話題:

網上有不少 React Router 文章了,例如:redux

爲什麼 jsliang 要屢次一舉?

  1. 你記錄你的,我記錄個人,互相不妨礙。
  2. 看這些跟看官網沒啥兩樣,因此我須要親自動手過一遍官網。
  3. 記錄我看官網的內容,順帶記錄我應用上去的實例,方便我下次回顧。

三 初試

返回目錄

當前版本"react-router-dom": "^5.0.0"

首先,在 Create React App 中,咱們引用 React Router:

  • npm i react-router-dom -S

而後,在 src 目錄下新建 pages 用來存放頁面,並修改 App.js:

案例:App.js

import React, { Fragment } from 'react';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import ScrollToTop from './components/ScrollToTop';
import Header from './components/Header';
import TimeLine from './pages/TimeLine';
import NotFound from './pages/404';

function App() {
  return (
    <Fragment> <BrowserRouter> <Header /> <ScrollToTop> <Switch> <Redirect from="/" to="/timeline" exact /> <Route path="/timeline" component={TimeLine}></Route> <Route component={NotFound}></Route> </Switch> </ScrollToTop> </BrowserRouter> </Fragment> ); } export default App; 複製代碼

最後,經過在 App.js 中如此定義,便可定義對應的組件,並渲染對應頁面和進行跳轉。

四 簡介

返回目錄

下面咱們拿一些經常使用的進行介紹:

import { 
  BrowserRouter,
  HashRouter,
  Redirect,
  Route,
  NavLink,
  Link,
  MemoryRouter,
  Switch,
  withRouter
} from "react-router-dom";
複製代碼
  1. <BrowserRouter>:路由組件包裹層。<Route><Link> 的包裹層。
  2. <HashRouter>:路由組件包裹層。相對於 <BrowserRouter> 來講,更適合靜態文件的服務器。
  3. <Redirect>:路由重定向。渲染 <Redirect> 將使導航到一個新的地址。
  4. <Route>:路由。定義一個路由頁面,用來匹配對應的組件(Component)和路由路徑。
  5. <NavLink>:活躍連接。當 URL 中的路徑等於該路由定義的路徑時,該標籤能夠呈現它定義的 activeClassName
  6. <Link>:連接。用來跳轉到 <Route> 對應的路由(Component) 中。
  7. <MemoryRouter>:暫未使用。<Router> 能在內存中保存 URL 的歷史記錄。很適合在測試環境和非瀏覽器環境中使用,例如 React Native。
  8. <Switch>:路由分組。渲染與該地址匹配的第一個子節點 <Route>或者 <Redirect>。能夠利用 <Switch> 作分組。
  9. <withRouter>:路由組合。經過 <withRouter> 高階組件訪問 history 對象的屬性和最近的 <Route>match。或者利用它來結合 Redux。

五 BrowserRouter

返回目錄

<BrowserRouter> 會爲你建立一個專門的 history 對象,用來記錄你的路由,從而可以返回上一頁或者跳轉到指定的路由頁面。

區別於 <HashRouter>,有響應請求的服務器時使用 <BrowserRouter>,使用的是靜態文件的服務器,則用 <HashRouter>

簡單案例:

<BrowserRouter>
  <Header /> <Route path="/" exact component={TimeLine}></Route> <Route path="/timeline" component={TimeLine}></Route> </BrowserRouter>
複製代碼

5.1 BrowserRouter 語法

返回目錄

import { BrowserRouter } from 'react-router-dom'

<BrowserRouter
  basename={optionalString}
  forceRefresh={optionalBool}
  getUserConfirmation={optionalFunc}
  keyLength={optionalNumber}
>
  <App/>
</BrowserRouter>
複製代碼

5.2 BrowserRouter - basename

返回目錄

  • 規則:basename: string

爲裏面的子目錄提供基礎路徑名,例如:

<BrowserRouter basename="/calendar">
  <Link to="/today"/> {/* 渲染爲 <a href="/calendar/today"> */} </BrowserRouter> 複製代碼

5.3 BrowserRouter - getUserConfirmation

返回目錄

  • 規則:getUserConfirmation: function

用於確認導航的功能。

// 默認使用 window.confirm。
const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

<BrowserRouter getUserConfirmation={getConfirmation}/>
複製代碼

5.4 BrowserRouter - forceRefresh

返回目錄

  • 規則:forceRefresh: bool

若是爲 true,則路由器將在頁面導航中使用整頁刷新

const supportsHistory = 'pushState' in window.history
<BrowserRouter forceRefresh={!supportsHistory}/>
複製代碼

5.5 BrowserRouter - keyLength

返回目錄

  • 規則:keyLength: number

設置它裏面路由的 location.key 的長度。默認爲 6。

key 的做用:點擊同一個連接時,每次該路由下的 location.key都會改變,能夠經過 key 的變化來刷新頁面。

<BrowserRouter keyLength={12}/>
複製代碼

六 HashRouter

返回目錄

使用 URLhash 部分(即 window.location.hash )的 <Router> 使 UIURL 保持同步。

重要提示:Hash 歷史記錄不支持 location.keylocation.state

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>
複製代碼

6.1 HashRouter - basename

返回目錄

  • 規則:basename: string

全部位置的基本 URL,格式正確的基本名應該有一個前導斜線,但結尾不能有斜線。

<HashRouter basename="/calendar"/>
<Link to="/today"/> 
{/* 渲染爲 <a href="/calendar/today"> */}
複製代碼

6.2 HashRouter - getUserConfirmation

返回目錄

  • 規則:getUserConfirmation: func

用於確認導航的功能。默認使用 window.confirm。

// this is the default behavior
const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

<HashRouter getUserConfirmation={getConfirmation}/>
複製代碼

6.3 HashRouter - hashType

返回目錄

  • 規則:hashType: string

用於 window.location.hash 的編碼類型。可用的值是:

  • slash - 建立 #/ 和的 #/sunshine/lollipops
  • noslash - 建立 # 和的 #sunshine/lollipops
  • hashbang - 建立 ajax crawlable,如 #!/#!/sunshine/lollipops

默認爲 slash

七 Link

返回目錄

在應用程序周圍提供聲明式的,可訪問的導航。

7.1 Link - to

返回目錄

  • 規則 1:to: string

連接位置的字符串表示,經過鏈接位置的路徑名,搜索和 hash 屬性建立。

<Link to='/courses?sort=name'>字符串形式跳轉</Link>
複製代碼
  • 規則 2:to: object

一個能夠具備如下任何屬性的對象:

  • pathname: 表示要連接到的路徑的字符串。
  • search: 表示查詢參數的字符串形式。
  • hash: 放入網址的 hash,例如 #a-hash
  • state: 狀態持續到 location
<Link to={{
  pathname: '/courses',          // 基礎路徑
  search: '?sort=name',          // 匹配字段
  hash: '#the-hash',             // 對應內鏈
  state: { fromDashboard: true } // 未知
}}>
  對象形式跳轉
</Link>
複製代碼

7.2 Link - replace

返回目錄

  • 規則:replace: bool

若是爲 true,則單擊連接將替換歷史堆棧中的當前入口,而不是添加新入口。

<Link to="/courses" replace>替換當前 hash 路徑</Link>
複製代碼

7.3 Link - other

返回目錄

還能夠傳遞想要放在 <a> 上的屬性,例如標題,IDclassName 等。

<Link to="/test" id="myTest">測試 1</Link>
複製代碼

返回目錄

八 NavLink

返回目錄

一個特殊版本的 Link,當它與當前 URL 匹配時,爲其渲染元素添加樣式屬性。

  • 高亮顯示首頁:<NavLink to="/timeline" activeClassName="active">首頁</NavLink>

8.1 NavLink - activeClassName

返回目錄

  • 規則:activeClassName: string

要給出的元素的類處於活動狀態時。默認的給定類是 active。它將與 className 屬性一塊兒使用。

<NavLink
  to="/faq"
  activeClassName="selected"
>FAQs</NavLink>
複製代碼

8.2 NavLink - activeStyle

返回目錄

  • 規則:activeStyle: object

當元素處於 active 時應用於元素的樣式。

<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}
>FAQs</NavLink>
複製代碼

8.3 NavLink - exact

返回目錄

  • 規則:exact: bool

若是爲 true,則僅在位置徹底匹配時才應用 active 的類/樣式。

<NavLink
  exact
  to="/profile"
>Profile</NavLink>
複製代碼

8.4 NavLink - isActive

返回目錄

  • 規則:isActive: function

一個爲了肯定連接是否處於活動狀態而添加額外邏輯的函數,若是你想作的不只僅是驗證連接的路徑名與當前 URL 的 pathname 是否匹配,那麼應該使用它

// 若是連接不只僅匹配 events/123,而是全部奇數連接都匹配
const oddEvent = (match, location) => {
  if (!match) {
    return false
  }
  const eventID = parseInt(match.params.eventID)
  return !isNaN(eventID) && eventID % 2 === 1
}

<NavLink
  to="/events/123"
  isActive={oddEvent}
>Event 123</NavLink>
複製代碼

九 MemoryRouter

返回目錄

<Router> 能在內存中保存 URL 的歷史記錄(並不會對地址欄進行讀寫)。很適合在測試環境和非瀏覽器環境中使用,例如 React Native。

<MemoryRouter>
  <App/>
</MemoryRouter>
複製代碼

9.1 MemoryRouter - initialEntries

返回目錄

  • 規則:initialEntries: array

history 棧中的一個 location 數組。這些多是具備 { pathname, search, hash, state } 或簡單的 URL 字符串的完整地址對象。

<MemoryRouter
  initialEntries={[ '/one', '/two', { pathname: '/three' } ]}
  initialIndex={1}
>
  <App/>
</MemoryRouter>
複製代碼

9.2 MemoryRouter - initialIndex

返回目錄

  • 規則:initialIndex: number

initialEntries 數組中的初始化地址索引。

9.3 MemoryRouter - getUserConfirmation

返回目錄

  • 規則:getUserConfirmation: function

用於確認導航的函數。在使用 <MemoryRouter> 時,直接使用 <Prompt>,你必須使用這個選項。

9.4 MemoryRouter - keyLength

返回目錄

  • 規則:keyLength: number

location.key的長度。默認爲 6。

十 Redirect

返回目錄

渲染 <Redirect> 將使導航到一個新的地址。這個新的地址會覆蓋 history 棧中的當前地址,相似服務器端(HTTP 3xx)的重定向。

咱們能夠設置某個路由重定向到另外一個路由,例以下面即對 / 徹底匹配重定向到 /timeline 頁面。

<Redirect from="/" to="/timeline" exact />
複製代碼

10.1 Redirect - from

返回目錄

  • 規則:from: string

重定向 from 的路徑名。能夠是任何 path-to-regexp 可以識別的有效的 URL 路徑。

全部匹配的 URL 參數都提供給 to 中的模式。

必須包含在 to 中使用的全部參數。

to 未使用的其餘參數將被忽略。

<Switch>
  <Redirect from="/old-path" to="/new-path" /> <Route path="/new-path" component={Place} /> </Switch> 複製代碼

10.2 Redirect - to

返回目錄

  • 規則:to: string

重定向到的 URL,能夠是任何 path-to-regexp 可以理解有效 URL 路徑。

to 中使用的 URL 參數必須由 from 覆蓋。

<Redirect to="/somewhere/else" />
複製代碼
  • 規則:to: object

重定向到的 locationpathname 能夠是任何 path-to-regexp 可以理解的有效的 URL 路徑。

<Redirect
  to={{
    pathname: "/login",
    search: "?utm=your+face",
    state: { referrer: currentLocation }
  }}
/>
複製代碼

10.3 Redirect - push

返回目錄

  • 規則:push: bool

true 時,重定向會將新地址推入 history 中,而不是替換當前地址。

<Redirect push to="/somewhere/else" />
複製代碼

10.4 Redirect - exact

返回目錄

  • 規則:exact: bool

徹底匹配 from

十一 Route

返回目錄

只要應用程序位置與 Route 的路徑匹配,組件就會被渲染。

11.1 Route - component

返回目錄

只有當位置匹配時纔會渲染的 React 組件。

<Route path="/user/:username" component={User}/>

const User = ({ match }) => {
  return <h1>Hello {match.params.username}!</h1>
}
複製代碼

11.2 Route - render

返回目錄

  • 規則:render: function

這容許方便的內聯渲染和包裹,而不是上面那種不想要的從新安裝的解釋

能夠傳遞一個在位置匹配時調用的函數,而不是使用屬性爲您建立新的 React element component,該 render 屬性接收全部相同的 route propscomponent 渲染屬性。

// 行內編寫
<Route path="/home" render={() => <div>Home</div>}/>

// 包裹分開寫
const FadingRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    <FadeIn>
      <Component {...props}/>
    </FadeIn>
  )}/>
)

<FadingRoute path="/cool" component={Something}/>
複製代碼

11.3 Route - children

返回目錄

  • 規則:children: function

有時你須要渲染路徑是否匹配位置。在這些狀況下,您可使用函數 children 屬性,它的工做原理與渲染徹底同樣,不一樣之處在於它是否存在匹配。

children 渲染道具接收全部相同的 route props 做爲 componentrender 方法,若是 RouteURL 不匹配,match 則爲 null ,這容許你動態調整你的 UI 界面,基於路線是否匹配,若是路線匹配咱們則添加一個 active 類。

<ul>
  <ListItemLink to="/somewhere"/>
  <ListItemLink to="/somewhere-else"/>
</ul>

const ListItemLink = ({ to, ...rest }) => (
  <Route path={to} children={({ match }) => (
    <li className={match ? 'active' : ''}>
      <Link to={to} {...rest}/>
    </li>
  )}/>
)
複製代碼

11.4 Route - path

返回目錄

  • 規則:path: string

任何 path-to-regexp 能夠解析的有效的 URL 路徑

<Route path="/users/:id" component={User}/>
複製代碼

11.5 Route - exact

返回目錄

  • 規則:exact: bool

若是爲 true,則只有在路徑徹底匹配 location.pathname 時才匹配。

path location.pathname exact matches?
/one /one/two true no
/one /one/two false yes
<Route exact path="/one" component={About}/>
複製代碼

jsliang 我的經驗:

  1. 加了 exact 屬性後,會徹底匹配路徑;若是沒有加,則二級路徑也會匹配當前路徑(例如 /timeline/book)。
<BrowserRouter>
  <Route path="/" exact component={TimeLine}></Route>
  <Route path="/timeline" component={TimeLine}></Route>
</BrowserRouter>
複製代碼
  1. 咱們能夠動態設置 extra 的值,從而判斷是否須要加載某個組件。
const Home = () => <div>Home</div>;

const App = () => {
  const someVariable = true;

  return (
    <Switch>
      {/* these are good */}
      <Route exact path="/" component={Home} />
      <Route
        path="/about"
        render={props => <About {...props} extra={someVariable} />}
      />
      {/* do not do this */}
      <Route
        path="/contact"
        component={props => <Contact {...props} extra={someVariable} />}
      />
    </Switch>
  );
};
複製代碼

11.6 Route - location

返回目錄

  • 規則:location: object

一個 <Route> 元素嘗試其匹配 path 到當前的歷史位置(一般是當前瀏覽器 URL)。可是,也能夠經過location 一個不一樣 pathname 的匹配。

11.7 Route - sensitive

返回目錄

  • 規則:sensitive: bool

若是路徑區分大小寫,則爲 true,則匹配。

path location.pathname sensitive matches?
/one /one true yes
/One /one true no
/One /one false yes
<Route sensitive path="/one" component={About}/>
複製代碼

十二 Switch

返回目錄

渲染與該地址匹配的第一個子節點 <Route>或者 <Redirect>

能夠利用 <Switch> 作分組,即當有匹配時,匹配對應 path 對應的組件;若是沒有匹配,則匹配 NotFound 頁面。

<BrowserRouter>
  <Header /> <Switch> <Route path="/" exact component={TimeLine}></Route> <Route path="/timeline" component={TimeLine}></Route> <Route component={NotFound}></Route> </Switch> </BrowserRouter>
複製代碼

十三 篇外一:history

返回目錄

history 是一個包,在你安裝 React Router 的時候,會做爲它依賴包安裝到項目中,因此你能夠直接使用 history 中的屬性和方法:

  • length - (number 類型) history 堆棧的條目數
  • action - (string 類型) 當前的操做(push, replace, pop)
  • location - (object 類型) 當前的位置。location 會具備如下屬性:
    • pathname - (string 類型) URL 路徑
    • search - (string 類型) URL 中的查詢字符串
    • hash - (string 類型) URL 的哈希片斷
    • state - (object 類型) 提供給例如使用 push(path, state) 操做將
  • location 放入堆棧時的特定 location 狀態。只在瀏覽器和內存歷史中可用
  • push(path, [state]) - (function 類型) 在 history 堆棧添加一個新條目
  • replace(path, [state]) - (function 類型) 替換在 history 堆棧中的當前條目
  • go(n) - (function 類型) 將 history 堆棧中的指針調整 n
  • goBack() - (function 類型) 等同於 go(-1)
  • goForward() - (function 類型) 等同於 go(1)
  • block(prompt) - (function 類型) 阻止跳轉

十四 篇外二:Code Splitting

返回目錄

隨着應用的增加,代碼包會隨着生長。

到最後你會發現,你打包後的 js 文件大地太多離譜。

因此,咱們須要經過代碼分割,依據不一樣的路由,加載不一樣的 js 文件。

  1. 安裝 React Loadable:npm i react-loadable -S
  2. 結合 React Router 和 React Loadable 進行 Code Spliting:
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';

const Loading = () => <div>Loading...</div>;

const Home = Loadable({
  loader: () => import('./routes/Home'),
  loading: Loading,
});

const About = Loadable({
  loader: () => import('./routes/About'),
  loading: Loading,
});

const App = () => (
  <Router>
    <Switch>
      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
    </Switch>
  </Router>
);
複製代碼
  1. 打包項目: npm run build

十五 篇外三:Scroll To Top

返回目錄

15.1 跳轉頁面後滾動到頂部

返回目錄

  1. 首先,在全局 components 文件中定義 ScrollToTop 文件夾,其中 index.js 內容爲:

src/components/ScrollToTop/index.js

import { Component } from 'react';
import { withRouter } from 'react-router-dom';

class ScrollToTop extends Component {
    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
          window.scrollTo(0, 0)
        }
    }
    render() {
        return this.props.children
    }
}
 
export default withRouter(ScrollToTop);
複製代碼
  1. 而後,在 App.js 或者其餘頁面中使用 ScrollToTop 功能:

src/App.js

import React, { Fragment } from 'react';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import ScrollToTop from './components/ScrollToTop';
import Header from './components/Header';
import TimeLine from './pages/TimeLine';
import NotFound from './pages/404';

function App() {
  return (
    <Fragment> <BrowserRouter> <Header /> <ScrollToTop> <Switch> <Redirect from="/" to="/timeline" exact /> <Route path="/timeline" component={TimeLine}></Route> <Route component={NotFound}></Route> </Switch> </ScrollToTop> </BrowserRouter> </Fragment> ); } export default App; 複製代碼
  1. 最後,咱們切換路由的時候,頁面就會滾動到頂部。

15.2 頁面滾動到頂部

返回目錄

暫未實現

十六 篇外四:Redux

返回目錄

在項目中,咱們更但願 React Router 和 React Redux 合併起來,這時候能夠:

// before
export default connect(mapStateToProps)(Something)

// after
import { withRouter } from 'react-router-dom'
export default withRouter(connect(mapStateToProps)(Something))
複製代碼

十七 總結

返回目錄

若是你純粹過文檔(官方文檔,jsliang 的文檔),你會以爲毫無趣味、了無生趣、乏味、沉悶……

因此,jsliang 的學法是:開啓了一個項目,邊翻閱文檔,邊應用到項目中,並進行 Mark 標記,以便下次使用。

如此,該文檔雖然完結了,可是仍未完結!完結的是我過完了官方文檔,未完結的是 React Router 在我項目中可能有其餘應用,須要我一一添加進來。


jsliang 廣告推送:
也許小夥伴想了解下雲服務器
或者小夥伴想買一臺雲服務器
或者小夥伴須要續費雲服務器
歡迎點擊 雲服務器推廣 查看!

知識共享許可協議
jsliang 的文檔庫梁峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議進行許可。
基於github.com/LiangJunron…上的做品創做。
本許可協議受權以外的使用權限能夠從 creativecommons.org/licenses/by… 處得到。

相關文章
相關標籤/搜索