react-route

155 阅读11分钟

React Router 中文文档

React Router 官方英文文档

react-router包含3个库,react-router、react-router-dom和react-router-native。

react-router提供最基本的路由功能,实际使⽤的时候我们不会直接安装react-router,⽽是根据应⽤运⾏的环境选择安装react-router-dom(在浏览器中使⽤)或react-router-native(在rn中使⽤)。

npm install --save react-router-dom

react-router-dom和react-router-native都依赖react-router,所以在安装时,react-router也会⾃动安装,创建web应⽤

react-router中奉⾏⼀切皆组件的思想,路由器-Router、链接-Link、路由-Route、独占-Switch、重 定向-Redirect都以组件形式存在。

基本使用

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

export default class RouterPage extends Component {
  render() {
    return (
      <div>
        <h3>RouterPage</h3>
        <Router>
          <Link to="/">首页</Link>
          <Link to="/user">用户中心</Link>

          <Switch>
            <Route
              exact
              path="/"
              component={HomePage}
            />
            <Route path="/user" component={UserPage} />
            <Route component={EmptyPage} />
          </Switch>
        </Router>
      </div>
    );
  }
}

class HomePage extends Component {
  render() {
    return (
      <div>
        <h3>HomePage</h3>
      </div>
    );
  }
}

class UserPage extends Component {
  render() {
    return (
      <div>
        <h3>UserPage</h3>
      </div>
    );
  }
}

class EmptyPage extends Component {
  render() {
    return (
      <div>
        <h3>404</h3>
      </div>
    );
  }
}

在web开发中,我们使用BrowserRouter组件作为外层的路由器进行包裹。

常见组件

<BrowserRouter>

使用HTML5历史API(pushState、replaceState和popstate事件)保持UI与URL同步的<Router>。

它有以下可选属性:

basename: string

所有位置的基本URL。如果您的应用程序是从服务器上的子目录提供服务的,您需要将其设置为子目录。 格式正确的基名称应该有一个前导斜杠,但不能有尾随斜杠。

getUserConfirmation: func

这个属性当window.confirm触发时,它才会执行;然后根据用户输入,是否确定跳转。因此,该属性要搭配<Prompt>组件来使用

代码示例:

export default class RouterPage extends Component {
  render() {
    const getUserConfirmation = (message, callback) => {
      // 这里可以使用自定义的弹窗组件来提示用户是否继续导航
      const allowNavigation = window.confirm(message);
      callback(allowNavigation);
    };
    
    return (
      <div>
        <h3>RouterPage</h3>
        <Router 
         getUserConfirmation={getUserConfirmation}
        >
          <Link to="/">首页</Link>
          <Link to="/user">用户中心</Link>
          <Switch>
            <Route
              exact
              path="/"
              component={HomePage}
              // children={() => <div>children</div>}
              // render={() => <div>render</div>}
            />
            <Route path="/user" component={UserPage} />
            <Route component={EmptyPage} />
          </Switch>
          <Prompt
            when={true}
            message={() => '确定要离开吗?'}
          />
        </Router>  window.confirm.
      </div>
    );
  }
}

forceRefresh: bool

如果为true,路由器将在页面导航上使用完整页面刷新。 你可能想用它来模仿传统的服务器渲染应用程序在页面导航之间进行全页面刷新的方式。

keyLength: number

属性用于指定在生成动态 key 时使用的字符长度。这个 key 被用于区分不同的 Route 组件, 并在组件更新时帮助 React 识别组件的变化。默认值是6.

<HashRouter>

它使用URL的哈希部分(即window.location.hash)来保持UI与URL同步。它不支持location.key or location.state,建议使用 <BrowserRouter>

它有以下可选属性:

basename: string

getUserConfirmation: func

hashType: string;用于window.location.hash的编码类型。可用值为:

这些选项是指在使用 BrowserRouter 时,创建 URL 中哈希部分的不同方式:

  • "slash":默认值,创建类似于 #/#/sunshine/lollipops 的哈希,其中哈希之后使用斜杠(/)作为分隔符。
  • "noslash":创建类似于 ##sunshine/lollipops 的哈希,其中哈希之后不使用斜杠分隔符。
  • "hashbang":创建类似于 #!/#!/sunshine/lollipops 的哈希,这种方式被称为“ajax crawlable”,但已经被 Google 废弃。

<Link>

提供仅当前应用程序的声明性、可访问的导航。

to: string

<Link to="/about">About</Link>

to: object 这里列出的是在 React Router 中使用 <Link> 组件时可用的一些属性:

  • pathname:一个字符串,表示要链接到的路径(即要跳转到的页面的路径)。
  • search:一个字符串,表示查询参数的字符串表示形式。可以用于在链接中传递额外的参数。
  • hash:一个哈希(#)字符串,用于指定要添加到 URL 中的哈希部分,例如 #a-hash
  • state:一个用于持久化到位置的状态对象。在链接中传递 state 可以在跳转后从 location 对象中获取该状态。
<Link
  to={{
    pathname: "/courses",
    search: "?sort=name",
    hash: "#the-hash",
    state: { fromDashboard: true }
  }}
/>

to: func 该函数会接收当前的位置对象作为参数,并返回表示目标位置的字符串或对象。

这个功能非常有用,因为它允许您根据应用的逻辑动态地决定要跳转的位置。例如,您可以根据用户的权限或某些条件来动态地决定要导航到哪个页面。

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

function MyComponent() {
  const isUserLoggedIn = true;

  const getTargetLocation = (currentLocation) => {
    if (isUserLoggedIn) {
      return "/dashboard";
    } else {
      return {
        pathname: "/login",
        state: { from: currentLocation.pathname }
      };
    }
  };

  return (
    <div>
      <h1>My Component</h1>
      <Link to={getTargetLocation}>Go to Dashboard or Login</Link>
    </div>
  );
}

replace: bool;当设置为 true 时,表示点击该链接时将替换当前的历史记录栈中的条目,而不是添加一个新的条目。

component: React.Component;该属性用于指定自定义的导航组件。如果您想要使用自己的导航组件来替代 <Link> 组件的默认行为,可以通过 component 属性传递您的自定义组件。

const FancyLink = React.forwardRef(({ navigate, ...props }, ref) => {
  return (
    <a ref={ref} {...props} onClick={handleClick}>💅 {props.children}</a>
  )
})

<Link to="/" component={FancyLink} />

<NavLink>

<Link> 的一个特殊版本,当当前 URL 与它指向的 URL 匹配时,会自动添加样式属性到渲染的元素上。下面是一个示例,展示如何使用 <NavLink> 并添加样式属性:

import React from "react";
import { NavLink } from "react-router-dom";

const Navigation = () => {
  return (
    <nav>
      {/* 使用 <NavLink> 组件,并添加样式属性 */}
      <NavLink to="/" exact activeClassName="active-link">
        Home
      </NavLink>
      <NavLink to="/about" activeClassName="active-link">
        About
      </NavLink>
      <NavLink to="/contact" activeClassName="active-link">
        Contact
      </NavLink>
    </nav>
  );
};

className: string | func

<NavLink
  to="/faq"
  className={isActive =>
    "nav-link" + (!isActive ? " unselected" : "")
  }
>
  FAQs
</NavLink>

style: object | func

<NavLink
  to="/faq"
  style={isActive => ({
    color: isActive ? "green" : "blue"
  })}
>
  FAQs
</NavLink>

exact: bool

exact 设置为 true 时,只有当链接的目标路径与当前路径完全匹配时,才会应用活动类或样式。如果设置为 false 或不设置该属性,默认行为是当链接的目标路径是当前路径的子路径时也会应用活动类或样式。

strict: bool

当设置为 true 时,将考虑路径中的尾部斜杠(trailing slash)来确定位置是否与当前 URL 匹配。

isActive: func

用于添加额外的逻辑来确定链接是否处于活动状态(active)。如果你想要进行更复杂的判断,而不仅仅是验证链接的路径名是否与当前 URL 的路径名匹配,可以使用该属性。

当设置 isActive 属性时,你可以传入一个函数,该函数接收两个参数:matchlocationmatch 参数表示链接所匹配的位置信息,location 参数表示当前的位置信息。在函数内部,你可以根据自定义的逻辑来判断链接是否应该处于活动状态,并返回一个布尔值,指示链接是否处于活动状态。

import React from "react";
import { NavLink } from "react-router-dom";

const Navigation = () => {
  const isActiveLink = (match, location) => {
    // 自定义判断逻辑,这里假设只有在星期一时,链接才处于活动状态
    return location.pathname === "/" && new Date().getDay() === 1;
  };

  return (
    <nav>
      {/* 使用 <NavLink> 组件,并设置 isActive 属性为自定义的 isActiveLink 函数 */}
      <NavLink to="/" isActive={isActiveLink}>
        Home
      </NavLink>
      <NavLink to="/about">About</NavLink>
      <NavLink to="/contact">Contact</NavLink>
    </nav>
  );
};

location: object

isActive比较当前历史记录位置(通常为当前浏览器URL)。要与不同的位置进行比较,可以通过location传递一个位置。

<Redirect>

一个用于导航到新位置的组件。当渲染 <Redirect> 组件时,它会导航到指定的新位置,这个新位置会覆盖当前在历史记录堆栈中的位置,就像服务器端的重定向(HTTP 3xx)一样。

import React from "react";
import { Redirect } from "react-router-dom";

const ProtectedPage = ({ isAuthenticated }) => {
  // 如果用户未登录,重定向到登录页面
  if (!isAuthenticated) {
    return <Redirect to="/login" />;
  }

  // 如果用户已登录,则显示受保护的页面内容
  return (
    <div>
      <h3>Protected Page</h3>
      {/* 受保护的页面内容 */}
    </div>
  );
};

export default ProtectedPage;

<Redirect>有以下重要的属性:

to: string

用于指定重定向的目标 URL。它是一个字符串,可以是任何被 path-to-regexp@^1.7.0 解析的有效 URL 路径。在 <Redirect> 组件中使用 to 属性,将会导致页面重定向到指定的 URL。

to: object

这个对象应该包含以下属性:

  • pathname: 一个有效的 URL 路径,可以是任何 path-to-regexp@^1.7.0 可以理解的路径模式。
  • search: 查询参数
  • hash: 哈希
  • state: 状态

push: bool

设置为 true 时,重定向将向历史记录中推入一个新条目,而不是替换当前的条目。

from:string

from 属性只能在 <Switch> 组件内部的 <Redirect> 组件中使用。在 React Router 中,<Switch> 组件用于只渲染第一个与当前 URL 匹配的子组件,而忽略后续匹配的组件。这样可以确保只有一个路由被渲染,避免多个路由同时匹配的问题。

注意: 当在 <Switch> 组件内部使用 <Redirect> 时,我们可以在 <Redirect> 上设置 from 属性来指定需要重定向的路径。这样,只有当用户访问指定的路径时,才会触发重定向。

exact: bool

exact 设置为 true 时,只有当链接的目标路径与当前路径完全匹配时,才会应用活动类或样式。如果设置为 false 或不设置该属性,默认行为是当链接的目标路径是当前路径的子路径时也会应用活动类或样式。

strict: bool

当设置为 true 时,将考虑路径中的尾部斜杠(trailing slash)来确定位置是否与当前 URL 匹配。

sensitive: bool,设置为true时,大小写敏感。

<Route>

Route 组件是 React Router 中最重要的组件之一,它是理解和灵活运用 React Router 的关键。它的最基本职责是在当前 URL 与其定义的路径匹配时,渲染一些 UI。

Route 组件有几个重要的属性:

  1. path: 定义一个 URL 路径,当当前 URL 与 path 匹配时,该 Route 组件就会渲染。
  2. componentrender: 这两个属性都用于指定要渲染的 UI 组件或函数。component 属性接受一个 React 组件,render 属性接受一个函数,该函数返回要渲染的 UI。当 path 匹配时,Route 组件会将匹配的 URL 作为 props 传递给指定的组件或函数。
  3. exact: 默认情况下,Route 组件是部分匹配的,也就是说,当 URL 的路径与 path 包含关系时,该 Route 组件都会匹配。如果希望只有当 URL 的路径与 path 完全一致时才匹配,可以设置 exact 属性为 true
  4. children: Route 组件可以嵌套在其他组件中,当父组件的 path 匹配时,它的 children 属性可以定义更细粒度的路径匹配。在这种情况下,无论父组件的 path 是否完全匹配,children 都会被渲染。
  5. location: 通过传递 location 属性,可以强制 Route 组件使用指定的 URL 来匹配,而不是当前浏览器的 URL。这对于动态地改变当前 URL 的情况非常有用。

通过组合使用不同的 Route 组件,我们可以创建复杂的路由结构,使不同的 URL 匹配不同的 UI 组件,从而实现多页面应用程序的导航和交互。Route 组件的强大和灵活性使得 React Router 成为 React 应用中处理路由的首选解决方案。

Route渲染优先级:children>component>render。

这三种⽅式互斥,你只能⽤⼀种

<Switch>

它用于包裹多个 <Route> 组件,并且只渲染第一个与当前 URL 匹配的 <Route> 组件。一旦找到匹配的路由,<Switch> 就会停止继续匹配并渲染该路由对应的组件,而不会继续渲染其他可能匹配的路由。

<Prompt>

<Prompt> 组件是 React Router 提供的一个用于在用户导航离开页面之前进行提示的组件。当你的应用程序处于一种状态,需要阻止用户导航离开(比如表单还没有完全填写),你可以渲染一个 <Prompt> 组件来提示用户。

<Prompt> 组件有以下属性:

  • when (boolean): 用于指示是否应该启用 <Prompt> 组件的功能。当 whentrue 时,<Prompt> 组件将生效,否则不会产生任何效果。
  • message (string | function): 当用户尝试导航离开页面时,message 属性指定的消息将用于提示用户。它可以是一个字符串,也可以是一个函数。如果是字符串,该字符串将直接用作提示消息。如果是函数,函数将接收一个对象作为参数,其中包含 locationaction 属性。你可以根据这些属性来动态生成提示消息。

hook

useHistory

useHistory 是 React Router 提供的一个自定义 Hook,它允许你访问 history 实例,以便在应用程序中进行导航。

当你在组件中使用 useHistory Hook 时,它会返回一个 history 实例。

useLocation

useLocation 是 React Router 提供的一个自定义 Hook,它返回一个表示当前 URL 的 location 对象。你可以将它视为类似于 useState 的 Hook,在 URL 改变时返回一个新的 location 对象。

useParams

useParams 是 React Router 提供的一个自定义 Hook,它返回一个包含 URL 参数的键值对的对象。你可以使用它来访问当前 <Route>match.params 对象。

在 React Router 中,当你在 <Route> 中定义了带有参数的路径,例如 /users/:id,当用户访问 /users/123 这样的路径时,:id 处的值 123 就会成为一个 URL 参数。使用 useParams Hook,你可以轻松地获取这些 URL 参数的值。

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

const UserProfile = () => {
  const { id } = useParams();

  return (
    <div>
      <h1>User Profile</h1>
      <p>User ID: {id}</p>
    </div>
  );
};

const App = () => {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/users/123">User 123</Link>
            </li>
            <li>
              <Link to="/users/456">User 456</Link>
            </li>
          </ul>
        </nav>

        <Route path="/users/:id" component={UserProfile} />
      </div>
    </Router>
  );
};

export default App;

useRouteMatch

useRouteMatch 是 React Router 提供的一个自定义 Hook,可以获取更多的匹配信息,包括 URL 的 urlparams

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

const UserProfile = () => {
  const match = useRouteMatch('/users/:id');
  const { id } = match.params;

  return (
    <div>
      <h1>User Profile</h1>
      <p>User ID: {id}</p>
    </div>
  );
};

const App = () => {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/users/123">User 123</Link>
            </li>
            <li>
              <Link to="/users/456">User 456</Link>
            </li>
          </ul>
        </nav>

        <Route path="/users/:id" component={UserProfile} />
      </div>
    </Router>
  );
};

export default App;

在上面的例子中,我们使用 useRouteMatch 自定义 Hook 来匹配 URL 中的 /users/:id 路径,然后获取 id 参数并在页面中显示出来。