如何使用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 主题页面 以了解练习和编程项目。