react 路由的幾種使用方式

江理彭于晏發表於2020-11-11

React Router包含了四個包

包名Description
react-routerReact Router核心api
react-router-domReact Router的DOM繫結,在瀏覽器中執行不需要額外安裝react-router
react-router-nativeReact Native 中使用,而實際的應用中,其實不會使用這個。
react-router-config靜態路由的配置

主要使用`react-router-dom

1.宣告式路由

import React, { Component } from 'react'
import { BrowserRouter as Router, Route, NavLink} from 'react-router-dom'
import './style.css'

const Home = () => <div>首頁</div>
const Kind = () => <div>分類</div>
const Cart = () => <div>購物車</div>
const User = () => <div>我的</div>

export default class App extends Component {
  render() {
    // children  --- 所有的路由都會渲染該路由對應的元件 
    // React路由宣告式跳轉 Link  NavLink
    return (
      <Router>
        <ul>
          <li><NavLink activeClassName="selected" to="/home">首頁</NavLink></li>
          <li><NavLink activeClassName="selected" to="/kind">分類</NavLink></li>
          <li><NavLink activeClassName="selected" to="/cart">購物車</NavLink></li>
          <li><NavLink activeClassName="selected" to="/user">我的</NavLink></li>
        </ul>
        <hr />
        //渲染元件的方式
        <Route path="/home" component = { Home } />
        <Route path="/kind" ><Kind /></Route>
        <Route path="/cart" render = { () => <Cart/> }></Route>
        <Route path="/user" component = { User } />
        {/* <Route path="/user" children = { () => <User/> }></Route> */}
      </Router>
    )
  }
}

2.程式設計式路由

...
// 程式設計式導航需要 使用 this.props.history 物件
// 如果當前元件沒有的話,可以引入 withRouter --- 高階元件
@withRouter
class App extends Component {
  state = { 
    currentIndex: 0
  }
  changePage = (path, index) => {
    return (e) => {
      this.setState({ currentIndex: index })
      this.props.history.push(path)
    }
  }
  render() {
    const { currentIndex } = this.state
    // 程式設計式跳轉
    return (
      <>
        <ul>
          <li className={ currentIndex === 0 ? 'active' : ''} onClick={ this.changePage('/home', 0) }>首頁</li>
          <li className={ currentIndex === 1 ? 'active' : ''} onClick={ this.changePage('/kind', 1) }>分類</li>
          <li className={ currentIndex === 2 ? 'active' : ''} onClick={ this.changePage('/cart', 2) }>購物車</li>
          <li className={ currentIndex === 3 ? 'active' : ''} onClick={ this.changePage('/user', 3) }>我的</li>
        </ul>
        ...
      </>
    )
  }
}

3.動態路由(路由傳參)

const Child = (props) => {
  console.log(props)//路由引數
  const type = props.match.params.type
  return (
    <div>
      child - { type }
    </div>
  )
}

class App extends Component {
  render() {
    return (
      <>
        ...
        <Route path="/:type" component = { Child } />
      </>
    )
  }
}

4.二級路由

import React, { Component } from 'react'
import { Route, NavLink, useRouteMatch } from 'react-router-dom'
import './style.css'
// 巢狀路由
// 分類下的 導航元件
const Phone = () => <div>手機</div>
const Wash = () => <div>洗衣機</div>
const Ice = () => <div>電冰箱</div>

// 預設的導航元件
const Home = () => <div>首頁</div>
const Cart = () => <div>購物車</div>
const User = () => <div>我的</div>
const Kind = () => {
  console.log(useRouteMatch())
  const { url } = useRouteMatch() // useRouteMatch只能在函式式元件中使用
  return (
    <div>
      分類
      <ul>
        <li><NavLink to={ `${ url }/phone`}>大哥大</NavLink></li>
        <li><NavLink to={ `${ url }/wash`}>洗衣機</NavLink></li>
        <li><NavLink to={ `${ url }/ice`}>電冰箱</NavLink></li>
      </ul>
      <hr />
      <Route path={ `${ url }/phone`} component = { Phone } />
      <Route path={ `${ url }/wash`} component = { Wash } />
      <Route path={ `${ url }/ice`} component = { Ice } />
    </div>
  )
}
class App extends Component {
  render() {
    return (
     ...
    )
  }
}

5.路由的重定向及精純匹配

import { Route, NavLink, useRouteMatch, Redirect, Switch, withRouter } from 'react-router-dom'

...

@withRouter
class App extends Component {
  render() {
    const pathname = '/' + this.props.location.pathname.split('/')[1]
    return (
      <>
        ...
        
        {/* Switch 只能選擇其中一個路由 */}
        <Switch >
          <Route path="/home" component = { Home } />
          <Route path="/kind" component = { Kind } />
          <Route path="/cart" component = { Cart } />
          <Route path="/user" component = { User } />
          {/* exact 精準匹配 只有當路由為 / 時,才會重定向 */}
          <Redirect path="/" exact to="/home" />
          {/* 404路由配置在最底下 */}
          <Route path="*" component = { NoMatch } />
        </Switch>
      </>
    )
  }
}

6.元件的遞迴呼叫

import React from 'react'
import { Switch, Route, Link, Redirect, useParams, useRouteMatch} from 'react-router-dom'
// 元件的遞迴呼叫 --- 不常見
const list = [
  { id: 0, name: '張三', friends: [1, 2]},
  { id: 1, name: '李四', friends: [0, 2]},
  { id: 2, name: '王五', friends: [0, 1, 3]},
  { id: 3, name: '麻六', friends: [0]}
]

const find = (id) => {
  return list.find( item => item.id === id)
}
const Person = (props) => {
  const { url } = useRouteMatch() // this.props.match
  // console.log(url)
  const { id } = useParams() // this.props.match.params
  const person = find(id*1)
  return (
    <>
      { person.name } 的朋友有:
      <ul>
        {
          person.friends.map((id, index) => {
            let per = find(id*1)
            return (
              <li key = { index }>
                <Link to={ `${url}/${ id }`}>
                  { per.name }
                </Link>
              </li>
            )
          })
        }
      </ul>
      {/* 形成了元件的遞迴呼叫 */}
      <Route path={ `${url}/:id`} component={Person}/>
    </>
  )
}
const App = () => {
  return (
    <Switch>
      <Route path='/:id' component={Person}/>
      <Redirect path="/" exact to="/0" />
    </Switch>
  )
}

export default App

相關文章