ReactJS - 路由


在Web应用程序中,路由是将Web URL绑定到Web应用程序中的特定资源的过程。在 React 中,它将 URL 绑定到组件。React 本身不支持路由,因为它基本上是一个用户界面库。React 社区提供了许多第三方组件来处理 React 应用程序中的路由。让我们学习 React Router,React 应用程序的首选路由库

安装反应路由器

让我们学习如何在 Expense Manager 应用程序中安装React Router组件。

打开命令提示符并转到我们应用程序的根文件夹。

cd /go/to/expense/manager

使用以下命令安装反应路由器。

npm install react-router-dom --save

概念

React 路由器提供了四个组件来管理 React 应用程序中的导航。

路由器- 路由器是顶级组件。它包含整个应用程序。

Link - 类似于 html 中的锚标记。它设置目标 URL 以及参考文本。

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

这里,to属性用于设置目标url。

交换机和路由- 两者一起使用。将目标 url 映射到组件。Switch是父组件,Route是子组件。Switch组件可以有多个Route组件,每个Route组件将特定的 url 映射到一个组件。

<Switch>
   <Route exact path="/">
      <Home />
   </Route>
   <Route path="/home">
      <Home />
   </Route>
   <Route path="/list">
      <ExpenseEntryItemList />
   </Route>
</Switch>

这里,path属性用于匹配url。基本上,Switch 的工作方式类似于编程语言中的传统 switch 语句。它按顺序将目标 url 与每个子路由(路径属性)进行匹配,并调用第一个匹配的路由。

除了路由器组件之外,React 路由器还提供了从 url 获取设置和获取动态信息的选项。例如,在文章网站中,url 可能附加有文章类型,并且需要动态提取文章类型并且必须使用该文章类型来获取特定类型的文章。

<Link to="/article/c">C Programming</Link>
<Link to="/article/java">Java Programming</Link>

...
...

<Switch>
  <Route path="article/:tag" children={<ArticleList />} />
</Switch>

然后,在子组件(类组件)中,

import { withRouter } from "react-router"

class ArticleList extends React.Component {
   ...
   ...
   static getDerivedStateFromProps(props, state) {
      let newState = {
         tag: props.match.params.tag
      }
      return newState;
   }
   ...
   ...
}
export default WithRouter(ArticleList)

这里,WithRouter使ArticleList组件能够通过props访问标签信息。

在功能组件中可以以不同的方式完成同样的事情 -

function ArticleList() {
   let { tag } = useParams();
   return (
      <div>
         <h3>ID: {id}</h3>
      </div>
   );
}

这里,useParams是React Router组件提供的自定义React Hooks。

嵌套路由

React 路由器也支持嵌套路由。React router 提供了另一个 React Hooks,useRouteMatch()来提取嵌套路由中的父路由信息。

function ArticleList() {
   // get the parent url and the matched path
   let { path, url } = useRouteMatch();

   return (
      <div>
         <h2>Articles</h2>
         <ul>
            <li>
               <Link to={`${url}/pointer`}>C with pointer</Link>
            </li>
            <li>
               <Link to={`${url}/basics`}>C basics</Link>
            </li>
         </ul>

         <Switch>
            <Route exact path={path}>
               <h3>Please select an article.</h3>
            </Route>
            <Route path={`${path}/:article`}>
               <Article />
            </Route>
         </Switch>
      </div>
   );
}
function Article() {
   let { article } = useParams();
   return (
      <div>
         <h3>The select article is {article}</h3>
      </div>
   );
}

这里,useRouteMatch返回匹配的路径和目标url。url 可用于创建下一级链接,path可用于映射下一级组件/屏幕。

创建导航

让我们学习如何通过在费用管理应用程序中创建可能的路由来进行路由。应用程序的最小屏幕如下 -

  • 主屏幕- 应用程序的登陆或初始屏幕

  • 费用列表屏幕- 以表格格式显示费用项目

  • 费用添加屏幕- 添加界面以添加费用项目

首先,按照创建React 应用程序章节中的说明,使用Create React AppRollup捆绑器创建一个新的React 应用程序,react-router-app

接下来,在您喜欢的编辑器中打开应用程序。

接下来,在应用程序的根目录下创建src文件夹。

接下来,在 src 文件夹下创建Components文件夹。

接下来,在src/components文件夹下创建一个文件Home.js并开始编辑。

接下来,导入React 库

import React from 'react';

接下来,从 React 路由器库导入Link 。

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

接下来,创建一个类 Home 并使用props调用构造函数。

class Home extends React.Component {
   constructor(props) {
      super(props);
   }
}

接下来,添加render()方法并显示欢迎消息以及添加和列出费用屏幕的链接。

render() {
   return (
      <div>
         <p>Welcome to the React tutorial</p>
         <p><Link to="/list">Click here</Link> to view expense list</p>
         <p><Link to="/add">Click here</Link> to add new expenses</p>
      </div>
   )
}

最后,导出组件。

export default Home;

Home组件的完整源代码如下 -

import React from 'react';
import { Link } from 'react-router-dom'

class Home extends React.Component {
   constructor(props) {
      super(props);
   }
   render() {
      return (
         <div>
            <p>Welcome to the React tutorial</p>
            <p><Link to="/list">Click here</Link> to view expense list</p>
            <p><Link to="/add">Click here</Link> to add new expenses</p>
         </div>
      )
   }
}
export default Home;

接下来,在src/components文件夹下创建ExpenseEntryItemList.js文件并创建ExpenseEntryItemList组件。

import React from 'react';
import { Link } from 'react-router-dom'

class ExpenseEntryItemList extends React.Component {
   constructor(props) {
      super(props);
   }
   render() {
      return (
         <div>
            <h1>Expenses</h1>
            <p><Link to="/add">Click here</Link> to add new expenses</p>
            <div>
               Expense list
            </div>
         </div>
      )
   }
}
export default ExpenseEntryItemList;

接下来,在src/components文件夹下创建ExpenseEntryItemForm.js文件并创建ExpenseEntryItemForm组件。

import React from 'react';
import { Link } from 'react-router-dom'

class ExpenseEntryItemForm extends React.Component {
   constructor(props) {
      super(props);
   }
   render() {
      return (
         <div>
            <h1>Add Expense item</h1>
            <p><Link to="/list">Click here</Link> to view new expense list</p>
            <div>
               Expense form
            </div>
         </div>
      )
   }
}
export default ExpenseEntryItemForm;

接下来,在src/components文件夹下创建一个文件App.css并添加通用 css 样式。

html {
   font-family: sans-serif;
}
a{
   text-decoration: none;
}
p, li, a{
   font-size: 14px;
}
nav ul {
   width: 100%;
   list-style-type: none;
   margin: 0;
   padding: 0;
   overflow: hidden;
   background-color: rgb(235,235,235);
}
nav li {
   float: left;
}
nav li a {
   display: block;
   color: black;
   text-align: center;
   padding: 14px 16px;
   text-decoration: none;
   font-size: 16px;
}
nav li a:hover {
   background-color: rgb(187, 202, 211);
}

接下来,在src/components文件夹下创建文件App.js并开始编辑。App组件的目的是在一个组件中处理所有屏幕。它将配置路由并启用到所有其他组件的导航。

接下来,导入 React 库和其他组件。

import React from 'react';

import Home from './Home'
import ExpenseEntryItemList from './ExpenseEntryItemList'
import ExpenseEntryItemForm from './ExpenseEntryItemForm'

import './App.css'

接下来,导入 React 路由器组件。

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

接下来,编写render()方法并配置路由。

function App() {
   return (
      <Router>
         <div>
            <nav>
               <ul>
                  <li>
                     <Link to="/">Home</Link>
                  </li>
                  <li>
                     <Link to="/list">List Expenses</Link>
                  </li>
                  <li>
                     <Link to="/add">Add Expense</Link>
                  </li>
               </ul>
            </nav>

            <Switch>
               <Route path="/list">
                  <ExpenseEntryItemList />
               </Route>
               <Route path="/add">
                  <ExpenseEntryItemForm />
               </Route>
               <Route path="/">
                  <Home />
               </Route>
            </Switch>
         </div>
      </Router>
   );
}

接下来,在src文件夹下创建一个文件index.js并使用App组件。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';

ReactDOM.render(
   <React.StrictMode>
      <App />
   </React.StrictMode>,
   document.getElementById('root')
);

最后,在根文件夹下创建一个public文件夹,并创建index.html文件。

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React router app</title>
   </head>
   <body>
      <div id="root"></div>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

接下来,使用 npm 命令为应用程序提供服务。

npm start

接下来,打开浏览器并在地址栏中输入http://localhost:3000并按回车键。

尝试导航链接并确认路由正常工作。

导航链接