在 React 应用中使用 React Router

187 阅读2分钟

最近在写的 React 版记账项目应用了路由库 React Router。它是通过管理 URL,实现组件的切换和状态的变化。在项目中用到的一些功能在此做一个学习记录。

安装

在使用 React Router之前得先创建一个 React 应用。

  1. 安装 create-react-app 并使用它创建一个 React 项目。
yarn global add create-react-app

create-react-app demo-app --template typescript		// 若使用 TS 则需安装 TS 依赖

cd demo-app

  1. 安装 react-router-dom
yarn add react-router-dom

yarn add --dev @types/react-router-dom 		// 若使用 TS 则需安装 TS 声明文件

基础用法

举个栗子:制作一个导航栏:有2个页面由路由器处理:一个主页,一个用户页面。 当单击不同的 Link,路由器呈现匹配对应的页面。

import React from "react";
import {BrowserRouter as Router,Switch,Route,Link} from "react-router-dom";
export default function App() {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/users">Users</Link></li>
          </ul>
        </nav>
        
        <Switch>
          <Route path="/users"><Users/></Route>
           <Route path="/"><Home /></Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {return <h2>Home1</h2>;}
function Users() {return <h2>Users2</h2>;}

Router

Router 组件本身只是一个容器,真正的路由要通过 Route 组件定义

  • Router 有两种模式:History 和 Hash
  • Hash:所以如果没有后台服务器,就只能用 Hash
  • History:如果有后台服务器,配置所有的路径到首页就能用 History 要使用路由器,只需确保将其呈现在元素层次结构的根目录下即可。

Route Matchers

路线匹配器

  • 两个路由匹配组件:Switch 和 Route。 当 Switch 被渲染,它会搜索其 children-Route 内容找到一个其 path 值能够与当前的 URL 匹配。当找到这一个对象时,它将渲染该组件。如果没有 Route 匹配项,则Switch 不呈现任何内容(null)。
import React from "react";
import {BrowserRouter as Router,Switch,Route,Link} from "react-router-dom";
export default function App() {
  return (
    <div>
      <Switch>
        <Route path="/about"><About /></Route>
        <Route path="/about/:id"><Contact /></Route>

        <Route path="/contact/:id"><Contact /></Route>
        <Route path="/contact"><AllContacts /></Route>
        
        <Route path="/"><Home/></Route>
        
        <Route path="*"><NotFound/></Route>
      </Switch>
    </div>
  );
}

注意!

  1. path = "/" 的路由将始终匹配 URL 的开头,渲染对应的 Home 组件,因为所有网址以 / 开头。 因此,我们通常将该 Route 放在最后
<Route exact path="/">		// 若不放在最后得加上 exact 
  1. 只要 path="/xxx" 放在了 path="/xxx/:id" 前面, 如果当前 URL 是 /xxx...,那么只能够渲染 /xxx 路由对应组件,其余的则被忽略。就像 /about
// 解决办法:
<Route path="/contact/:id"><Contact /></Route>
<Route path="/contact"><AllContacts /></Route>
  1. path="*" 表示若存在与所有 path 不匹配的 Route ,则渲染 NotFound 组件

  2. 若不想担心由 Route 书写顺序引发的 bug ,建议给每一个 Route 加上 exact

导航

提供了一个 Link 标签创建链接的组件。相当于 a 标签

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

NavLink 是一种特殊类型的 Link

<NavLink to="/detail" activeClassName="selected">React</NavLink>
//	<a href="/redetailact" className="selected">React</a>

API

useHistory

  • 回退功能
  • 跳转到指定页面

举个栗子:

import {useHistory} from "react-router-dom";

const GoBack = () =>{
  const history = useHistory();
  const onClickBack = () => {history.goBack();};
  const onClickPush = () => {history.push("/detail");};
  
  return (
    <button onClick={onClickBack}>回退</button>
    <button onClick={onClickPush}>跳到 detail 页面</button>
  )
}

useParams

  • 获取 URL 参数 useParams 返回 URL 参数的键/值对的对象。使用它来访问当前配对的组件
import React from "react";
import {BrowserRouter as Router,Switch,Route,useParams} from "react-router-dom";

function BlogPost() {
  let { slug } = useParams();
  return <div>Now showing post {slug}</div>;
}

ReactDOM.render(
  <Router>
    <Switch>
      <Route exact path="/"><HomePage /></Route>
      <Route path="/blog/:slug"><BlogPost /></Route>
    </Switch>
 </Router>,
  node
);