如何使用ReactRouterv4设置条件和响应式路由
介绍
React 中的响应式路由涉及根据用户设备的视口为用户提供不同的路由。 CSS 媒体查询通常用于实现此目的,但这会限制您使用 CSS 道具显示或不显示不同的元素。 使用响应式路由,您现在可以直接根据屏幕尺寸为不同用户提供 React 应用程序的完整独立视图。
在本教程中,我们将向您展示如何在您的 React 应用程序中实现路由和提供响应式路由。 按照本教程,您将构建一个用户仪表板应用程序,该应用程序根据用户设备屏幕的大小为用户提供不同的路线。
先决条件
要完成本教程,您需要:
- Node.js 安装在本地,您可以按照【X57X】如何安装Node.js 并创建本地开发环境【X126X】进行。
本教程已使用 Node v14.2.0、npm v6.14.5、react v16.3.2、react-router-dom v5.2.0 和 react-media v1.10.0 进行了验证.
第 1 步 — 设置项目
要启动您的项目,请使用 npx 和 create-react-app 创建一个新的 React 应用程序:
npx create-react-app responsive-routing
然后,导航到新的项目目录:
cd responsive-routing
接下来,安装成功构建此演示所需的必要模块。 这些模块是 react-router-dom 和 react-media。 您可以通过运行以下命令来安装它们:
npm install react-router-dom@5.2.0 react-media@1.10.0
现在,您可以通过运行以下命令来启动应用程序:
npm start
注意: 虽然不需要路由,但本教程使用 Bulma CSS 框架进行样式和布局。
您可以使用以下终端命令添加 Bulma:
npm install bulma@0.6.2
并将以下内容添加到您的 index.js 中:
index.js
import 'bulma/css/bulma.css';
在这一步中,您已经设置了项目并添加了 Bulma 框架用于样式和布局。
第 2 步 - 添加 React 路由器
要将路由添加到您的项目,您需要修改 index.js 文件以在元素层次结构的根部呈现路由器:
nano index.js
首先,从 react-router-dom 导入 BrowserRouter 并将其别名为 Router:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from "react-router-dom";
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
然后,将 <React> 替换为 <Router>:
index.js
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
您的应用程序现在已设置为使用 React Router。
页面中心的 GitHub 徽标将用作应用程序的导航部分。
在您的 src 目录中,创建一个名为 Nav 的新目录:
mkdir src/Nav
您将需要添加 GitHub 徽标并将其保存为 logo.svg 在此目录中。
接下来,在这个目录下创建一个index.js文件:
nano src/Nav/index.js
并添加以下代码:
src/Nav/index.js
import React from 'react';
import './Nav.css';
import logo from './logo.svg';
const Nav = () => (
<nav>
<img src={logo} alt="Logo" />
</nav>
);
export default Nav;
接下来,在这个目录下创建一个Nav.css文件:
nano src/Nav/Nav.css
导航组件具有以下样式:
src/Nav/Nav.css
nav {
display: flex;
justify-content: center;
height: 50px;
margin-bottom: 10px;
}
nav > img {
display: block;
width: 50px;
height: auto;
}
现在,让我们通过修改 App.js 文件来渲染 Nav 组件。
nano src/App.js
导入 Nav 组件并在您的 App 组件中使用它:
src/App.js
import React, { Component } from 'react';
import Nav from './Nav';
class App extends Component {
render() {
return (
<div>
<Nav />
</div>
);
}
}
export default App;
现在,当您在 Web 浏览器中打开您的应用程序时,您应该会看到您添加的徽标。
第 4 步 — 创建 UsersCard 组件
用户卡将负责显示用户的详细信息。 它将包含 avatar、name 和 username 等信息。 它还将显示 followers、following 和 repos。
在您的应用程序的 src 目录中,创建一个新的 Users 目录:
mkdir src/Users
接下来,在这个目录下创建一个UsersCard.js文件:
nano src/Users/UsersCard.js
并添加以下代码:
src/Users/UsersCard.js
import React from 'react';
import { Link } from 'react-router-dom';
import './UsersCard.css'
const UsersCard = ({ user, match }) => <Link to={`${match.url}/${user.id}`} className="column card">
<img src={user.avatar} alt=""/>
<p className="users-card__name">{user.name}</p>
<p className="users-card__username">@{user.username}</p>
<div className="users-card__divider"></div>
<div className="users-card__stats">
<div>
<p>{user.followers}</p>
<span>Followers</span>
</div>
<div>
<p>{user.following}</p>
<span>Following</span>
</div>
<div>
<p>{user.repos}</p>
<span>Repositories</span>
</div>
</div>
</Link>;
export default UsersCard;
react-router-dom 中的 Link 组件用于允许用户在单击卡片时导航以查看单个用户的详细信息。
例如,如果 UsersCard 的 id 为 10009,则 Link 组件将生成如下 URL:
localhost:3000/10009
localhost:3000表示当前 URL。10009表示$user.id。
所有这些信息都将在渲染组件时传递。
接下来,在这个目录下创建一个UsersCard.css文件:
nano src/users/UsersCard.css
UsersCard 组件具有以下样式:
src/Users/UsersCard.css
.card {
border-radius: 2px;
background-color: #ffffff;
box-shadow: 0 1.5px 3px 0 rgba(0, 0, 0, 0.05);
max-width: 228px;
margin: 10px;
display: flex;
flex-direction: column;
align-items: center;
padding: 0;
}
.card img {
width: 50px;
height: auto;
border-radius: 50%;
display: block;
padding: 15px 0;
}
.users-card__name {
font-weight: 400;
font-size: 16.5px;
line-height: 1.19;
letter-spacing: normal;
text-align: left;
color: #25292e;
}
.users-card__username {
font-size: 14px;
color: #707070;
}
.users-card__divider {
border: solid 0.5px #efefef;
width: 100%;
margin: 15px 0;
}
.users-card__stats {
display: flex;
}
.users-card__stats p {
font-size: 20px;
}
.users-card__stats div {
margin: 10px;
text-align: center;
}
.users-card__stats span {
color: #707070;
font-size: 12px;
}
此时您有一个 UsersCard 组件。 接下来,您需要在列表中显示这些卡片。
第 5 步 — 创建 UsersList 组件
要让您的应用程序列出用户,您需要首先创建一个 UsersList 组件。
在src/Users目录下创建一个UsersCard.js文件:
nano UsersList.js
让我们编辑UsersList.js如下。
首先,您将进行必要的导入:
src/Users/UsersList.js
import React from 'react'; import UsersCard from './UsersCard'; import './UsersList.css';
定义一个 listOfUsersPerRow 函数,该函数将构建一个 UsersCard 与它们在 users 数组中的位置一致:
// ...
const listOfUsersPerRow = (users, row, itemsPerRow, match) =>
users
.slice((row - 1) * itemsPerRow, row * itemsPerRow)
.map(user => <UsersCard user={user} key={user.id} match={match} />);
定义一个 listOfRows 函数,该函数将构建包含 UsersCard 的 "columns",由 itemsPerRow 的数量定义:
// ...
const listOfRows = (users, itemsPerRow, match) => {
const numberOfUsers = users.length;
const rows = Math.ceil(numberOfUsers / itemsPerRow);
return Array(rows)
.fill()
.map((val, rowIndex) => (
<div className="columns">
{listOfUsersPerRow(users, rowIndex + 1, itemsPerRow, match)}
</div>
));
};
listOfUsersPerRow 和 listOfRows 函数可确保您在每行中的卡片数量不超过指定数量。
然后,使用函数创建一个 UsersList:
src/Users/UsersList.js
//...
const UsersList = ({ users, itemsPerRow = 2, match }) => (
<div className="cards">
<h3 className="is-size-3 has-text-centered">Users</h3>
{listOfRows(users, itemsPerRow, match)}
</div>
);
export default UsersList;
接下来,在这个目录下创建一个UsersList.css文件:
nano src/Users/UsersList.css
UsersList 组件具有以下样式:
src/Users/UsersList.css
.cards {
margin-left: 20px;
}
.columns {
margin-top: 0;
}
此时,您有一个由 UsersCard 组成的 UsersList 组件。 接下来,您将需要单个用户的详细视图。
第 6 步 — 创建 UsersDetails 组件
当从UsersList中单击单个UsersCard时,将在详细信息部分下显示单个UsersCard。
在src/Users目录下创建一个UsersDetails.js文件:
nano UsersDetails.js
并添加以下代码:
src/Users/UsersDetails.js
import React from 'react';
import UsersCard from './UsersCard';
const UsersDetails = ({ user, match }) => <div>
<h3 className="is-size-3 has-text-centered">Details</h3>
<UsersCard user={user} match={match} />
</div>;
export default UsersDetails;
此时,您有一个 UsersDetails 组件。 接下来,您将显示 UsersLists 和 UsersDetails。
第 7 步 — 创建 UsersDashboard 组件
要制作仪表板组件,您将显示 UsersList,当单击 UsersCard 时,在屏幕一侧显示 UsersDetails 而无需重新加载页面。
在src/Users目录下创建一个UsersDashboard.js文件:
nano src/Users/UsersDashboard.js
并添加以下代码:
src/Users/UsersDashboard.js
import React from 'react';
import { Route } from 'react-router-dom';
import UsersList from './UsersList';
import UsersDetails from './UsersDetails';
const UsersDashboard = ({ users, user, match }) => (
<div className="columns">
<div className="column">
<UsersList users={users} match={match} />
</div>
<div className="column">
<Route
path={match.url + '/:id'}
render={props => (
<UsersDetails
user={
users.filter(
user => user.id === parseInt(props.match.params.id, 10)
)[0]
}
match={match}
/>
)}
/>
</div>
</div>
);
export default UsersDashboard;
在此代码段中,您使用了 react-router-dom 提供的 Route 组件作为组件,用于在点击卡片时显示特定的用户详细信息。
至此,您已经拥有了应用程序的所有组件。
第 8 步 — 将它们放在一起
现在,让我们把这一切放在一起。
重新访问 App.js 文件:
nano src/App.js
添加 Redirect 和 UsersDashboard:
src/App.js
import React, { Component } from 'react';
import { Route, Redirect } from 'react-router-dom';
import Nav from './Nav';
import UsersDashboard from './Users/UsersDashboard';
import './App.css';
添加包含 users 数组的 state:
src/App.js
//...
class App extends Component {
state = {
users: [
{
id: 39191,
avatar: 'https://avatars0.githubusercontent.com/u/39191?v=4',
name: 'Paul Irish',
username: 'paulirish',
followers: '12k',
following: '1k',
repos: '1.5k'
},
// ... other user data
]
};
// ...
}
// ...
将 Route 和 UsersDashboard 添加到 App 组件:
class App extends Component {
// ...
render() {
return (
<div className="App">
<Nav />
<Route
path="/dashboard"
render={props => (
<UsersDashboard users={this.state.users} {...props} />
)}
/>
<Redirect from="/" to="/dashboard"/>
<Redirect from="/users" to="/dashboard"/>
</div>
);
}
}
// ...
现在,在 Web 浏览器中查看您的应用程序时,您应该会看到 UsersList。 单击 UsersCard 时,您将看到它显示在 UsersDetails 中。
第 9 步 — 设置响应式路由
当用户访问此应用程序时,无论屏幕大小如何,他们都会获得相同的视图和功能。 在成熟的应用程序中,为用户提供他们可以正常享受的体验是很好的。 一种方法是为他们提供与其确切设备尺寸相匹配的视图。 您现在将在您的应用程序中实现它。
大屏访问应用时,跳转到应用的/dashboard路径,小屏查看时,跳转到应用的/users路径应用。
将 src/App.js 文件更新为如下所示:
src/App.js
import React, { Component } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom'; // add Switch
import Media from 'react-media'; // add Media
import Nav from './Nav';
import UsersList from './Users/UsersList'; // add UsersList
import UsersDetails from './Users/UsersDetails'; // add UsersDetails
import UsersDashboard from './Users/UsersDashboard';
import './App.css';
class App extends Component {
// ...
render() {
return (
<div className="App">
<Nav />
<Media query="(max-width: 599px)">
{matches =>
matches ? (
<Switch>
<Route
exact
path="/users"
render={props => (
<UsersList users={this.state.users} {...props} />
)}
/>
<Route
path="/users/:id"
render={props => (
<UsersDetails
user={
this.state.users.filter(
user =>
user.id === parseInt(props.match.params.id, 10)
)[0]
}
{...props}
/>
)}
/>
<Redirect from="/" to="/users"/>
<Redirect from="/dashboard" to="/users"/>
</Switch>
) : (
<Switch>
<Route
path="/dashboard"
render={props => (
<UsersDashboard users={this.state.users} {...props} />
)}
/>
<Redirect from="/" to="/dashboard"/>
<Redirect from="/users" to="/dashboard"/>
</Switch>
)
}
</Media>
</div>
);
}
}
export default App;
在此代码段中,您使用了 Media 组件来检查屏幕的大小。 如果屏幕宽度小于 599px,您可以为不同的路由设置想要显示的内容,并将 / 和 /dashboard 路由重定向到 [X169X ] 路线。
如果屏幕尺寸大于 599px,您将显示在上一步中建立的完整用户仪表板。
运行应用程序:
npm start
与您的应用程序交互并调整您的屏幕大小,以查看在与应用程序交互时如何以不同方式处理路由。
根据屏幕尺寸提供不同的路由提供了媒体查询之外的东西,因为您现在可以根据用户的设备尺寸为用户提供专门设计的组件。
结论
在本文中,您了解了使用 React 的基于组件的路由以及如何在您的 React 应用程序中实现条件渲染。
有关本教程的完整代码示例,请查看 GitHub 上的 responsive-routing 存储库。
如果您想了解有关 React 的更多信息,请查看我们的 如何在 React.js 中编码,或查看 我们的 React 主题页面 以了解练习和编程项目。