介绍
React 中的响应式路由涉及根据用户设备的视口为用户提供不同的路由。CSS 媒体查询通常用于实现此目的,但这会限制您使用 CSS 道具显示或不显示不同的元素。通过响应式路由,您现在可以直接根据不同用户的屏幕尺寸为他们提供 React 应用程序的完整独立视图。
在本教程中,我们将向您展示如何在 React 应用程序中实现路由和响应式路由。按照本教程,您将构建一个用户仪表板应用程序,该应用程序根据用户设备屏幕的大小为用户提供不同的路由。
先决条件
要完成本教程,您需要:
- Node.js 安装在本地,您可以按照如何安装 Node.js 和创建本地开发环境来完成。
本教程已通过 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
:
import 'bulma/css/bulma.css';
在这一步中,您已经设置了项目并添加了用于样式和布局的 Bulma 框架。
第 2 步 – 添加 React 路由器
要将路由添加到您的项目,您需要修改index.js
文件以在元素层次结构的根部渲染路由器:
- nano index.js
首先,导入BrowserRouter
fromreact-router-dom
并将其别名为Router
:
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>
:
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
您的应用程序现在已设置为使用 React Router。
第 3 步 – 创建Nav
组件
页面中央的 GitHub 徽标将用作应用程序的导航部分。
在您的src
目录中,创建一个名为的新目录Nav
:
- mkdir src/Nav
您需要添加 GitHub 徽标并将其保存logo.svg
在此目录中。
接下来,index.js
在此目录中创建一个文件:
- nano 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
导航组件具有以下样式:
nav {
display: flex;
justify-content: center;
height: 50px;
margin-bottom: 10px;
}
nav > img {
display: block;
width: 50px;
height: auto;
}
现在,让我们Nav
通过修改App.js
文件来渲染组件。
- nano src/App.js
导入Nav
组件并在您的App
组件中使用它:
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
并添加以下代码:
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;
在Link
从组件react-router-dom
被用来允许用户导航被点击卡时查看单个用户的详细信息。
例如,如果 aUsersCard
有一个id
of 10009
,Link
组件将生成一个像这样的 URL:
localhost:3000/10009
localhost:3000
表示当前的 URL。10009
代表$user.id
.
所有这些信息都将在组件呈现时传递。
接下来,UsersCard.css
在此目录中创建一个文件:
- nano src/users/UsersCard.css
该UsersCard
组件具有以下样式:
.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
组件。
UsersCard.js
在src/Users
目录中创建一个文件:
- nano UsersList.js
让我们编辑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
函数,该函数将构建"columns"
包含UsersCard
由 数量定义的 s 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
:
//...
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
组件具有以下样式:
.cards {
margin-left: 20px;
}
.columns {
margin-top: 0;
}
此时,您有一个UsersList
由UsersCard
s组成的组件。接下来,您将需要单个用户的详细视图。
第 6 步 – 创建UsersDetails
组件
UsersCard
从 中单击单曲时UsersList
,单曲UsersCard
将显示在详细信息部分下。
UsersDetails.js
在src/Users
目录中创建一个文件:
- nano 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
单击a 时UsersDetails
,在屏幕一侧显示 ,而无需重新加载页面。
UsersDashboard.js
在src/Users
目录中创建一个文件:
- nano 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;
在此代码段中,您使用了Route
提供的组件react-router-dom
作为组件,以在单击卡片时显示特定的用户详细信息。
此时,您已拥有应用程序的所有组件。
第 8 步 – 将它们放在一起
现在,让我们把这一切放在一起。
重温App.js
文件:
- nano src/App.js
添加Redirect
和UsersDashboard
:
import React, { Component } from 'react';
import { Route, Redirect } from 'react-router-dom';
import Nav from './Nav';
import UsersDashboard from './Users/UsersDashboard';
import './App.css';
添加state
包含以下内容的数组users
:
//...
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
文件更新为如下所示:
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
路线重定向到/users
路线。
如果屏幕大小大于599px
,则显示上一步中建立的完整用户仪表板。
运行应用程序:
npm start
与您的应用程序交互并调整您的屏幕大小,以查看在与应用程序交互时如何以不同方式处理路由。
根据屏幕尺寸提供不同的路由提供了媒体查询之外的功能,因为您现在可以根据用户的设备尺寸为用户提供专门设计的组件。
结论
在本文中,您了解了使用 React 进行基于组件的路由以及如何在 React 应用程序中实现条件渲染。
有关本教程的完整代码示例,请查看responsive-routing
GitHub 上的存储库。
如果您想了解有关 React 的更多信息,请查看我们的How To Code in React.js系列,或查看我们的 React 主题页面以获取练习和编程项目。