如何使用 React Router v4 设置条件路由和响应路由

介绍

在 React 中,响应式路由涉及根据设备的视图端口向用户提供不同的路由。CSS 媒体查询通常用于实现这一目标,但这限制了您使用 CSS 代理来显示或不显示不同的元素。

在本教程中,我们将向您展示如何在您的 React 应用程序中实施路由和服务响应路线. 通过遵循本教程,您将构建一个用户仪表板应用程序,根据设备屏幕的大小为用户提供不同的路线。

Demo showing the cards adjusting to the size of the page

前提条件

要完成本教程,您将需要:

本教程已通过 Node v14.2.0、npm v6.14.5、react v16.3.2、react-router-dom v5.2.0 和 react-media v1.10.0 进行验证。

步骤1 - 设置项目

要启动您的项目,请使用 npxcreate-react-app 创建一个新的 React 应用程序:

1npx create-react-app responsive-routing

然后,导航到新项目目录:

1cd responsive-routing

接下来,安装必要的模块,你将需要成功构建这个演示文稿. 这些模块是反应路由器-dom反应媒体

现在,您可以通过运行命令启动应用程序:

1npm start

<$>[注] **注:**虽然不需要路由,但本教程使用了 Bulma CSS 框架来设计和布局。

您可以使用以下终端命令添加 Bulma:

1npm install [email protected]

并将以下内容添加到您的index.js:

1[label index.js]
2import 'bulma/css/bulma.css';

美元

在此步骤中,您已经设置了您的项目,并添加了Bulma框架来设计和布局。

步骤 2 – 添加 React Router

要将路由添加到您的项目中,您需要修改您的 index.js 文件以使路由器位于元素等级的根基:

1nano index.js

首先,从react-router-dom导入BrowserRouter,并将其命名为Router:

1[label index.js]
2import React from 'react';
3import ReactDOM from 'react-dom';
4import { BrowserRouter as Router } from "react-router-dom";
5import './index.css';
6import App from './App';
7import registerServiceWorker from './registerServiceWorker';

然后,用React代替Router:

1[label index.js]
2ReactDOM.render(
3  <Router>
4    <App />
5  </Router>,
6  document.getElementById('root')
7);

您的应用程序现在已设置为使用 React Router。

步骤 3 – 创建Nav组件

页面中心的GitHub标志将作为您的应用程序的导航部分。

在您的src目录中,创建一个名为Nav的新目录:

1mkdir src/Nav

您需要添加 GitHub 标志并将其保存为logo.svg在此目录中。

接下来,在这个目录中创建一个index.js文件:

1nano src/Nav/index.js

然后添加以下代码:

 1[label src/Nav/index.js]
 2import React from 'react';
 3import './Nav.css';
 4import logo from './logo.svg';
 5
 6const Nav = () => (
 7  <nav>
 8    <img src={logo} alt="Logo" />
 9  </nav>
10);
11
12export default Nav;

接下来,在这个目录中创建一个Nav.css文件:

1nano src/Nav/Nav.css

导航组件具有以下风格:

 1[label src/Nav/Nav.css]
 2nav {
 3  display: flex;
 4  justify-content: center;
 5  height: 50px;
 6  margin-bottom: 10px;
 7}
 8
 9nav > img {
10  display: block;
11  width: 50px;
12  height: auto;
13}

现在,让我们通过修改App.js文件来渲染Nav组件。

1nano src/App.js

导入Nav组件并在您的应用组件中使用它:

 1[label src/App.js]
 2import React, { Component } from 'react';
 3import Nav from './Nav';
 4
 5class App extends Component {
 6  render() {
 7    return (
 8      <div>
 9        <Nav />
10      </div>
11    );
12  }
13}
14
15export default App;

现在,当您在 Web 浏览器中打开应用时,您应该看到您添加的标志。

步骤 4 – 创建用户卡组件

用户卡将负责显示用户的详细信息,它将包含avatarnameusername等信息,还会显示followers,followersrepos

在您的应用程序的src目录中,创建一个新的用户目录:

1mkdir src/Users

接下来,在这个目录中创建一个UsersCard.js文件:

1nano src/Users/UsersCard.js

然后添加以下代码:

 1[label src/Users/UsersCard.js]
 2import React from 'react';
 3import { Link } from 'react-router-dom';
 4import './UsersCard.css'
 5
 6const UsersCard = ({ user, match }) => <Link to={`${match.url}/${user.id}`} className="column card">
 7  <img src={user.avatar} alt=""/>
 8  <p className="users-card__name">{user.name}</p>
 9  <p className="users-card__username">@{user.username}</p>
10  <div className="users-card__divider"></div>
11  <div className="users-card__stats">
12    <div>
13      <p>{user.followers}</p>
14      <span>Followers</span>
15    </div>
16    <div>
17      <p>{user.following}</p>
18      <span>Following</span>
19    </div>
20    <div>
21      <p>{user.repos}</p>
22      <span>Repositories</span>
23    </div>
24  </div>
25</Link>;
26
27export default UsersCard;

react-router-dom中使用的链接组件允许用户在点击卡时导航,查看单个用户的详细信息。

例如,如果一个用户卡有一个ID10009,则链接组件将生成这样的URL:

1localhost:3000/10009
  • localhost:3000 表示当前的 URL.
  • 10009 表示 $user.id.

所有这些信息将在组件渲染时传递。

接下来,在这个目录中创建一个UsersCard.css文件:

1nano src/users/UsersCard.css

UsersCard组件具有以下风格:

 1[label src/Users/UsersCard.css]
 2.card {
 3  border-radius: 2px;
 4  background-color: #ffffff;
 5  box-shadow: 0 1.5px 3px 0 rgba(0, 0, 0, 0.05);
 6  max-width: 228px;
 7  margin: 10px;
 8  display: flex;
 9  flex-direction: column;
10  align-items: center;
11  padding: 0;
12}
13
14.card img {
15  width: 50px;
16  height: auto;
17  border-radius: 50%;
18  display: block;
19  padding: 15px 0;
20}
21
22.users-card__name {
23  font-weight: 400;
24  font-size: 16.5px;
25  line-height: 1.19;
26  letter-spacing: normal;
27  text-align: left;
28  color: #25292e;
29}
30
31.users-card__username {
32  font-size: 14px;
33  color: #707070;
34}
35
36.users-card__divider {
37  border: solid 0.5px #efefef;
38  width: 100%;
39  margin: 15px 0;
40}
41
42.users-card__stats {
43  display: flex;
44}
45
46.users-card__stats p {
47  font-size: 20px;
48}
49
50.users-card__stats div {
51  margin: 10px;
52  text-align: center;
53}
54
55.users-card__stats span {
56  color: #707070;
57  font-size: 12px;
58}

在这一点上,你有一个UsersCard组件,接下来,你需要在列表中显示这些卡片。

步骤 5 – 创建用户列表组件

要让您的应用程序列出用户,您需要先创建一个用户列表组件。

src/Users目录中创建一个UsersCard.js文件:

1nano UsersList.js

让我们以以下方式编辑UsersList.js

首先,你会做必要的进口:

1[label src/Users/UsersList.js]
2import React from 'react';
3import UsersCard from './UsersCard';
4import './UsersList.css';

定义一个listOfUsersPerRow函数,将构建一个UsersCard,匹配其在用户系列中的位置:

1// ...
2
3const listOfUsersPerRow = (users, row, itemsPerRow, match) =>
4  users
5    .slice((row - 1) * itemsPerRow, row * itemsPerRow)
6    .map(user => <UsersCard user={user} key={user.id} match={match} />);

定义一个listOfRows函数,将构建包含UsersCard的``列,定义为itemsPerRow`的数量:

 1// ...
 2
 3const listOfRows = (users, itemsPerRow, match) => {
 4  const numberOfUsers = users.length;
 5  const rows = Math.ceil(numberOfUsers / itemsPerRow);
 6
 7  return Array(rows)
 8    .fill()
 9    .map((val, rowIndex) => (
10    <div className="columns">
11        {listOfUsersPerRow(users, rowIndex + 1, itemsPerRow, match)}
12    </div>
13  ));
14};

listOfUsersPerRowlistOfRows功能确保每个行上没有超过指定的卡片数。

然后,使用这些函数创建一个用户列表:

 1[label src/Users/UsersList.js]
 2//...
 3
 4const UsersList = ({ users, itemsPerRow = 2, match }) => (
 5  <div className="cards">
 6    <h3 className="is-size-3 has-text-centered">Users</h3>
 7    {listOfRows(users, itemsPerRow, match)}
 8  </div>
 9);
10
11export default UsersList;

接下来,在这个目录中创建一个UsersList.css文件:

1nano src/Users/UsersList.css

UsersList组件具有以下风格:

1[label src/Users/UsersList.css]
2.cards {
3  margin-left: 20px;
4}
5
6.columns {
7  margin-top: 0;
8}

在此时,你有一个由UsersCard组成的UsersList组件,接下来,你需要一个个别用户的详细视图。

步骤 6 – 创建用户细节组件

当单个用户卡用户列表中点击时,单个用户卡将在详细信息部分中显示。

src/Users目录中创建一个UsersDetails.js文件:

1nano UsersDetails.js

然后添加以下代码:

 1[label src/Users/UsersDetails.js]
 2import React from 'react';
 3import UsersCard from './UsersCard';
 4
 5const UsersDetails = ({ user, match }) => <div>
 6  <h3 className="is-size-3 has-text-centered">Details</h3>
 7    <UsersCard user={user} match={match} />
 8  </div>;
 9
10export default UsersDetails;

在此时,你有一个用户细节组件,接下来,你会显示用户列表用户细节

步骤 7 — 创建用户Dashboard组件

要创建仪表板组件,您将显示用户列表,并在点击用户卡时,在屏幕侧面显示用户详细信息,而无需重新加载页面。

src/Users目录中创建一个UsersDashboard.js文件:

1nano src/Users/UsersDashboard.js

然后添加以下代码:

 1[label src/Users/UsersDashboard.js]
 2import React from 'react';
 3import { Route } from 'react-router-dom';
 4import UsersList from './UsersList';
 5import UsersDetails from './UsersDetails';
 6
 7const UsersDashboard = ({ users, user, match }) => (
 8  <div className="columns">
 9    <div className="column">
10      <UsersList users={users} match={match} />
11    </div>
12    <div className="column">
13      <Route
14        path={match.url + '/:id'}
15        render={props => (
16          <UsersDetails
17            user={
18              users.filter(
19                user => user.id === parseInt(props.match.params.id, 10)
20              )[0]
21            }
22            match={match}
23          />
24        )}
25      />
26    </div>
27  </div>
28);
29
30export default UsersDashboard;

在本片中,您使用了由react-router-dom提供的Route组件作为组件,在单击卡时显示特定用户细节。

此时此刻,您有您的应用程序的所有组件。

第8步:把一切都放在一起

现在,让我们把这一切放在一起。

查看App.js文件:

1nano src/App.js

添加重定向用户面板:

1[label src/App.js]
2import React, { Component } from 'react';
3import { Route, Redirect } from 'react-router-dom';
4import Nav from './Nav';
5import UsersDashboard from './Users/UsersDashboard';
6import './App.css';

添加包含一组用户状态:

 1[label src/App.js]
 2//...
 3
 4class App extends Component {
 5  state = {
 6    users: [
 7      {
 8        id: 39191,
 9        avatar: 'https://avatars0.githubusercontent.com/u/39191?v=4',
10        name: 'Paul Irish',
11        username: 'paulirish',
12        followers: '12k',
13        following: '1k',
14        repos: '1.5k'
15      },
16      // ... other user data
17    ]
18  };
19
20  // ...
21}
22
23// ...

RouteUsersDashboard添加到您的App组件中:

 1class App extends Component {
 2  // ...
 3
 4  render() {
 5    return (
 6      <div className="App">
 7        <Nav />
 8        <Route
 9          path="/dashboard"
10          render={props => (
11            <UsersDashboard users={this.state.users} {...props} />
12          )}
13        />
14        <Redirect from="/" to="/dashboard"/>
15        <Redirect from="/users" to="/dashboard"/>
16      </div>
17    );
18  }
19}
20
21// ...

现在,当您在 Web 浏览器中查看您的应用程序时,您应该看到一个用户列表。当您点击用户卡,您将看到它显示在用户细节

第9步:设置响应式路由

当用户访问这个应用程序时,无论屏幕大小如何,他们都会得到相同的视图和功能。在全面的应用程序中,它是好的给用户体验,他们可以正确地享受。

在大屏幕上访问应用程序时,用户将被重定向到应用程序的/dashboard路线,而在小屏幕上查看时,用户将被重定向到应用程序的/users路线。

更新「src/App.js」檔案,看起來像這樣:

 1[label src/App.js]
 2import React, { Component } from 'react';
 3import { Route, Switch, Redirect } from 'react-router-dom'; // add Switch
 4import Media from 'react-media'; // add Media
 5import Nav from './Nav';
 6import UsersList from './Users/UsersList'; // add UsersList
 7import UsersDetails from './Users/UsersDetails'; // add UsersDetails
 8import UsersDashboard from './Users/UsersDashboard';
 9import './App.css';
10
11class App extends Component {
12  // ...
13
14  render() {
15    return (
16      <div className="App">
17        <Nav />
18        <Media query="(max-width: 599px)">
19          {matches =>
20            matches ? (
21              <Switch>
22                <Route
23                  exact
24                  path="/users"
25                  render={props => (
26                    <UsersList users={this.state.users} {...props} />
27                  )}
28                />
29                <Route
30                  path="/users/:id"
31                  render={props => (
32                    <UsersDetails
33                      user={
34                        this.state.users.filter(
35                          user =>
36                            user.id === parseInt(props.match.params.id, 10)
37                        )[0]
38                      }
39                      {...props}
40                    />
41                  )}
42                />
43                <Redirect from="/" to="/users"/>
44                <Redirect from="/dashboard" to="/users"/>
45              </Switch>
46            ) : (
47              <Switch>
48                <Route
49                  path="/dashboard"
50                  render={props => (
51                    <UsersDashboard users={this.state.users} {...props} />
52                  )}
53                />
54                <Redirect from="/" to="/dashboard"/>
55                <Redirect from="/users" to="/dashboard"/>
56              </Switch>
57            )
58          }
59        </Media>
60      </div>
61    );
62  }
63}
64
65export default App;

如果屏幕宽度小于599px,你会为不同的路线设置要显示的内容,并将//dashboard路线重定向到/users路线。

如果屏幕大小大于599px,则如前一步所示,将显示完整的用户仪表板。

运行应用程序:

1npm start

与应用程序互动,并调整屏幕大小,以查看在与应用程序互动时如何不同地处理路线。

根据屏幕大小提供不同的路径提供超越媒体查询的功能,因为您现在可以根据设备大小为用户提供专门设计的组件。

结论

在本文中,您介绍了React的基于组件的路由以及如何在React应用程序中实施条件渲染。

对于本教程的完整代码样本,请查看 GitHub 上的 responsive-routing 存储库。

如果您想了解更多关于 React 的信息,请查看我们的 如何在 React.js 中编码系列,或查看 我们的 React 主题页面以获取练习和编程项目。

Published At
Categories with 技术
Tagged with
comments powered by Disqus