React 快速上手 - 07 前端路由 react-router

react

目錄

React 快速上手 - 07 前端路由 react-router

目標

  • 基礎使用
  • 參數傳遞
  • 路由匹配
  • 轉換動畫
  • 跳轉路由

環境

  • react 16
  • react-router 4
  • react-router-dom 4
  • react-transition-group

0. 安裝

react-router

經過官網咱們能夠發現 react-router 能夠用在 web 網站端 native 設備端css

咱們這裏針對 web 網站端 安裝html

yarn add react-router-dom

react-router 會包自動依賴安裝前端

1. 先跑一個簡單例子

  • 代碼示範
import React, {Component} from 'react'
import {HashRouter as Router, Route, Link, Switch} from 'react-router-dom'

const Home = () => (
  <div>
    <h2>首頁</h2>
  </div>
)
const About = () => (
  <div>
    <h2>關於</h2>
  </div>
)

class RouterView extends Component {
  render() {
    return (
      <Router>
        <div>
          <ul>
            <li>
              <Link to="/">首頁</Link>
            </li>
            <li>
              <Link to="/about">關於</Link>
            </li>
          </ul>

          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/about" component={About} />
          </Switch>
        </div>
      </Router>
    )
  }
}

export default RouterView
  • 代碼結構
最外層須要包裹組件 <Router>
組件 <Route> 就是你看到的組件內容,放在哪裏就哪裏顯示
組件 <Link> 是頁面連接
  • 動圖說明

基礎路由

  • codepen

https://codepen.io/ducafecat/...html5

2. 基礎使用

2.1 BrowserRouter 仍是 HashRouter

  • BrowserRouter 是須要服務端配合, 是基於html5的pushState和replaceState的,不少瀏覽器不支持,存在兼容性問題。
連接地址長這樣 http://localhost:3000/about
  • HashRouter 是瀏覽器端解析路由
連接地址長這樣 http://localhost:3000#/about
  • 靈活切換
import {HashRouter as Router, Route, Link, Switch} from 'react-router-dom'
//import {BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom'

<Router>
  ...
</Router>
我用 as Router 作了別名,方便切換

2.2 組件 <Route> 屬性 exact 徹底匹配

<Route path="/about" component={About} />

exact=false 的時候 path 等於 /about /about/me 都能匹配react

可是 exact=true 的時候 只匹配 path 等於 /aboutgit

2.3 組件 <Route> 屬性 strict 末尾斜槓的匹配

<Route strict path="/about/" component={About} />

strict=true 路由請求末尾必須帶 /github

2.4 組件 <Link>

生成路由連接web

  • 屬性 to: string

路由地址字符串redux

<Link to="/about?me=haha">關於</Link>
  • 屬性 to: object

路由對象segmentfault

<Link to={{
  pathname: '/courses',
  search: '?sort=name',
  hash: '#the-hash',
  state: { fromDashboard: true }>關於</Link>
  • 屬性 replace: bool

設置 true 替換瀏覽器對象 history 爲當前路由,按回退按鈕時會發現以前的路由被替換了

2.5 組件 <NavLink>

生成路由連接的基礎上,若是是當前路由設置激活樣式

  • 屬性 activeClassName: string

樣式名稱

<NavLink to="/about" activeClassName="selected">關於</NavLink>
  • 屬性 activeStyle: object

樣式對象

<NavLink to="/about" activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}>關於</NavLink>
  • 屬性 isActive: func

判斷函數

const checkIsActive = (match, location) => {
  if (!match) {
    return false
  }
  ...
  return true
}

<NavLink to="/about" isActive={checkIsActive}>關於</NavLink>

2.6 組件 <Switch>

只渲染出第一個與當前訪問地址匹配的 <Route><Redirect>

不然你有幾個 <Route> 都會顯示

2.7 組件 <Redirect>

路由重定向

<Switch>
  <Redirect from='/users/:id' to='/users/profile/:id'/>
  <Route path='/users/profile/:id' component={Profile}/>
</Switch>

當請求 /users/:id 被重定向去 '/users/profile/:id'

  • 屬性 from: string

須要匹配的將要被重定向路徑。

  • 屬性 to: string

重定向的 URL 字符串

  • 屬性 to: object

重定向的 location 對象

  • 屬性 push: bool

若爲真,重定向操做將會把新地址加入到訪問歷史記錄裏面,而且沒法回退到前面的頁面。

2.8 組件 <Prompt>

當用戶離開當前頁面前作出一些提示。

  • 屬性 message: string

當用戶離開當前頁面時,設置的提示信息。

<Prompt message="肯定要離開?" />

Prompt

  • 屬性 message: func

當用戶離開當前頁面時,設置的回掉函數

<Prompt message={location => `肯定要去 ${location.pathname} ?`} />

Prompt-func

  • 屬性 when: bool

決定是否啓用 Prompt

3. 參數傳遞

3.1 編寫路由定義

<Route path="/topics/:topicId" component={Topic} />

:topicId 定義參數

3.2 編寫接收組件

const Topic = ({match}) => (
  <div>
    <h3>參數: {match.params.topicId}</h3>
  </div>
)

match.params 就是傳遞的參數

3.3 完整例子

代碼

import React, {Component} from 'react'
import {BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom'

const Topic = ({match}) => (
  <div>
    <h3>參數: {match.params.topicId}</h3>
  </div>
)

class RouterView extends Component {
  render() {
    return (
      <Router>
        <div>
          <ul>
            <li>
              <Link to="/topics/rendering">Rendering with React</Link>
            </li>
            <li>
              <Link to="/topics/components">Components</Link>
            </li>
            <li>
              <Link to="/topics/props-v-state">Props v. State</Link>
            </li>
          </ul>

          <Switch>
            <Route path="/topics/:topicId" component={Topic} />
          </Switch>
        </div>
      </Router>
    )
  }
}

export default RouterView

動圖效果

參數傳遞

4. 沒有匹配

代碼

import React, {Component} from 'react'
import {BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom'

const Back = () => (
  <div>
    <h2>首頁</h2>
  </div>
)

const NoMatch = () => (
  <div>
    <h2>沒有匹配</h2>
  </div>
)

class RouterView extends Component {
  render() {
    return (
      <Router>
        <div>
          <ul>
            <li>
              <Link to="/back">返回</Link>
            </li>
            <li>
              <Link to="/also/will/not/match">路由請求</Link>
            </li>
          </ul>

          <Switch>
            <Route path="/back" component={Back} />
            <Route component={NoMatch} />
          </Switch>
        </div>
      </Router>
    )
  }
}

export default RouterView
在最下面寫個默認組件,都沒命中,就是這個了

動圖效果

沒有匹配

5. 嵌套路由

react-route4 中嵌套要這樣寫

<Switch>
  <Route path="/article" component={ArticleList} />
  <Route path="/article/:id" component={Article} />
  <Route path="/article/:id/recommend" component={ArticleRecommend} />
</Switch>

寫成一排,業務以下

path 組件 說明
/article ArticleList 文章列表
/article/:id Article 文章
/article/:id/recommend ArticleRecommend 文章推薦

6. 自定義路由

適合用來作權限檢查

6.1 建立自定義 Route

const isAuthenticated = true
const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      isAuthenticated ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

6.2 使用自定義路由

...
<Route path="/public" component={Public} />
<Route path="/login" component={Login} />
<PrivateRoute path="/protected" component={Protected} />

7. 轉換動畫

這裏用到了 react-transition-group

動圖效果

轉換動畫

7.1 安裝

yarn add react-transition-group

7.2 編寫動畫 css

文件 fade.css

.fade-enter {
  opacity: 0;
  z-index: 1;
}

.fade-enter-active {
  opacity: 1;
  transition: opacity 250ms ease-in;
}

.fade-exit {
  opacity: 0;
}
名稱 說明
fade-enter 動畫啓動
fade-enter-active 動畫激活
fade-exit 動畫離開

其它動畫樣式名字能夠參考 css-transition

7.3 導入包和動畫樣式

...
import {TransitionGroup, CSSTransition} from 'react-transition-group'
import './fade.css'

TransitionGroup, CSSTransition 必須導入

7.4 編寫樣式

const styles = {}

styles.fill = {
  position: 'relative',
  height: '200px',
  width: '500px'
}

styles.content = {
  ...styles.fill,
  top: '40px',
  textAlign: 'center',
  height: '120px'
}

styles.nav = {
  padding: 0,
  margin: 0,
  position: 'absolute',
  top: 0,
  height: '40px',
  width: '100%',
  display: 'flex'
}

styles.navItem = {
  textAlign: 'center',
  flex: 1,
  listStyleType: 'none',
  padding: '10px'
}

styles.hsl = {
  color: 'white',
  paddingTop: '20px',
  fontSize: '30px',
  height: '120px'
}

styles.rgb = {
  color: 'white',
  paddingTop: '20px',
  fontSize: '30px',
  height: '120px'
}

這是 react 的樣式對象,固然你也能夠寫成 .css 文件

7.5 編寫導航

const NavLink = props => (
  <li style={styles.navItem}>
    <Link {...props} style={{color: 'inherit'}} />
  </li>
)

7.6 編寫展現組件

// 切換區域 A
const HSL = ({match: {params}}) => (
  <div
    style={{
      ...styles.fill,
      ...styles.hsl,
      background: `hsl(${params.h}, ${params.s}%, ${params.l}%)`
    }}
  >
    hsl({params.h}, {params.s}%, {params.l}%)
  </div>
)

// 切換區域 B
const RGB = ({match: {params}}) => (
  <div
    style={{
      ...styles.fill,
      ...styles.rgb,
      background: `rgb(${params.r}, ${params.g}, ${params.b})`
    }}
  >
    rgb({params.r}, {params.g}, {params.b})
  </div>
)

7.7 編寫容器組件

const RouterView = () => (
  <Router>
    <Route
      render={({location}) => (
        <div style={styles.fill}>
          <Route
            exact
            path="/"
            render={() => <Redirect to="/hsl/10/90/50" />}
          />

          <ul style={styles.nav}>
            <NavLink to="/hsl/10/90/50">Red</NavLink>
            <NavLink to="/hsl/120/100/40">Green</NavLink>
            <NavLink to="/rgb/33/150/243">Blue</NavLink>
            <NavLink to="/rgb/240/98/146">Pink</NavLink>
          </ul>

          <div style={styles.content}>
            <TransitionGroup>
              <CSSTransition key={location.key} classNames="fade" timeout={300}>
                <Switch location={location}>
                  <Route exact path="/hsl/:h/:s/:l" component={HSL} />
                  <Route exact path="/rgb/:r/:g/:b" component={RGB} />
                  <Route render={() => <div>Not Found</div>} />
                </Switch>
              </CSSTransition>
            </TransitionGroup>
          </div>
        </div>
      )}
    />
  </Router>
)
  • codepen

https://codepen.io/ducafecat/...

代碼

參考

相關文章
相關標籤/搜索