ReactJS – 路由

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

安装React 路由器Routing

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

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

cd /go/to/expense/manager

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

npm install react-router-dom --save

概念

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

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

Link – 类似于 html 中的锚标记。它将目标 url 与参考文本一起设置。

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

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

Switch & Route – 两者一起使用。将目标 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 路由器提供了另一个 React Hooks,使用RouteMatch()来提取嵌套路由中的父路由信息。

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可用于映射下一级组件/屏幕。

创建导航

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

  • 主屏幕– 应用程序的登陆或初始屏幕
  • Expense list screen费用列表屏幕– 以表格格式显示费用项目
  • Expense add screen费用添加屏幕– 添加界面以添加费用项目

首先,按照创建 React 应用程序章节中的说明,使用Create React AppRollup bundler创建一个新的 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,回车。

尝试浏览链接并确认路由工作正常。