React实例之完善布局菜单(三)

接着上篇的内容继续。规划界面布局。界面分为三个部分,左边为菜单部分,右边上部有个 80 px 高度左右的功能区,下面是主内容区。 依据这个设计,我们进行下面的步骤:

在 SMenu项目中创建一个目录: SLayout, 这个目录里我们存储各种布局,我们先来示例一种,其它的我们根据需要可以自行设计。在这个目录中创建FullPage.jsx 文件

// SLayout/FullPage.jsximport Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';function FullPage({ sideMenu, pageHeader , children }) {return (<Paper className='d-flex overflow-hidden position-absolute w-100 h-100 p-0 m-0'><Box className='h-100'>{sideMenu}</Box><Box className='d-flex overflow-hidden position-relative flex-grow-1'><Box className="d-flex flex-column overflow-auto p-0 m-0 position-relative flex-grow-1 flex-nowrap"><BoxclassName="w-100 p-3 border-bottom"sx={{ height: 68 }}>{ pageHeader }</Box><Box className="p-0 w-100 h-100">{children }</Box></Box></Box></Paper>)
}export default FullPage;

这个没什么好说的,就是主要就是利用Flex的特殊用 Bootstrap 对界面进行布局,没什么难度。

现在我们利用这个布局把所用的元素添加进来。在SMenu项目目录下创建一个测试文件: SideMenuTest.jsx :

// SideMenuTest.jsx
import VerticalSplitIcon from '@mui/icons-material/VerticalSplit';
import Box from '@mui/material/Box';
import SideMenu from "./SMenu/SideMenu";
import SToggleButton from './SMenu/_SToggleButton';
import { useSideMenuBadgeUpdate } from './SMenu/_SMenuHooks';
import FullPage from './SLayout/FullPage';
import Typography from '@mui/material/Typography';
import Stack from '@mui/material/Stack';
import ToggleThemeButton from './STheme/TaggleThemeButton';function SideMenuTest() {const updateBadge = useSideMenuBadgeUpdate();const onClickHandler = (id, title, idPath, titlePath) => {console.log(id, title, idPath, titlePath);updateBadge(id, 0);}return (<FullPagesideMenu={<SideMenutitle="侧边菜单测试系统"logo="/logo.png"hClick = {()=>{console.log("headerOnClick")}}mClick={onClickHandler} />}pageHeader={<Stackdirection="row"justifyContent="space-between"alignItems="center"spacing={2}className='w-100'><SToggleButton icon={<VerticalSplitIcon />} /><ToggleThemeButton /></Stack>}><Box className="w-100 h-100 d-flex flex-grow-1 justify-content-center align-items-center"><Typography variant='h1'>欢迎来到码蚁基地</Typography></Box></FullPage>)
}export default SideMenuTest;

上面有个按钮组件是切换 Theme 模式的,<ToggleThemeButton/>的功能很简单,就是调用我们先前设计好的 Theme 中的Hook, 这里给出一个示例,供参考。我们在 STheme目录下创建这个组件文件:ToggleThemeButton.jsx

// STheme/TaggleThemeButton.jsximport IconButton from '@mui/material/IconButton';
import useToggleTheme from "./useToggleThemeHook";
import { useTheme } from '@emotion/react';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';function ToggleThemeButton() {const toggleSTheme = useToggleTheme();const theme = useTheme();return (<IconButton sx={{ ml: 1 }} onClick={() => { toggleSTheme(); }} color="inherit">{theme.palette.mode === 'dark' ? <Brightness7Icon /> : <Brightness4Icon />}</IconButton>)
}export default ToggleThemeButton;

是不是很简单。

现在我们在SMenu项目目录下的 App.jsx中引入这个 SideMenuTest 组件就OK 了。如下所示:

import SideMenuTest from "./SideMenuTest";
import SideMenuProvider from "./SMenu/SideMenuProvider";
import sideMenuConfigData from "./menuData";function App() {return (<SideMenuProvider menuData={sideMenuConfigData}><SideMenuTest /></SideMenuProvider>)
}export default App;

现在的目录结构看起来应该是这个样子的:

在这里插入图片描述

你现在运行以后就可以看到一开始所示的动图的效果了。为了查看Badge的效果,我们在 SideMenuProvider中将Badge的初始化值更改一下。这里改成了 30 ,如下所示:

/*** 获取菜单项的id集合, 用于初始化菜单项的徽章,本菜单的每个Item都有一个id属性,用于唯一标识菜单项。* @param menuConfig * @returns */
function initBadge(menuConfig){let ids = {};menuConfig.forEach((element) => {const name = element.id;ids = { ...ids, [name]: 30 };if (element.children) {const children = element.children;children.forEach(el => {const subName = el.id;ids = { ...ids, [subName]: 30 };})}});return ids;
}

注意,我在 SideMenuTest 中传入菜单项点击事件的回调中 是这样写的:

const updateBadge = useSideMenuBadgeUpdate();
const onClickHandler = (id, title, idPath, titlePath) => {console.log(id, title, idPath, titlePath);updateBadge(id, 0); // 单击菜单项后清除 消息提示。 }

现在的效果应该是这样的:

在这里插入图片描述

现在我们已经验证了菜单的功能 ,但是让菜单和路由结合起来才是我们真正的目的。

设计路由界面

根据我之前 React Router相关的内容知识,我们来要准备一个WellCome页面,一个 Page404 页面, 还有一个无数据匹配的空页面。

在App.jsx 文件中,我们做出如下更改和配置:

import SideMenuTest from "./SideMenuTest";
import SideMenuProvider from "./SMenu/SideMenuProvider";
import sideMenuConfigData from "./menuData";
import Typography from '@mui/material/Typography';import {createBrowserRouter,RouterProvider,
} from "react-router-dom";
import Page404 from "./SPages/Page404";
import Wellcome from "./SPages/Wellcome";
import NoMatchRoute from "./SPages/NoMatchRoute";const router = createBrowserRouter([{path: "/",element: <SideMenuTest />,errorElement: <Page404 />,children: [{path: "userCenter",element: <Typography variant='h1'>这是个人中心页面模块</Typography>,},{index: true,element: <Wellcome />},{path: "*",element: <NoMatchRoute />}]},
]);function App() {return (<SideMenuProvider menuData={sideMenuConfigData}><RouterProvider router={router} /></SideMenuProvider>)
}export default App;

我们配置了 Index 路由, 还配置了 * 路由,这个路由是当前路径下子路由没有匹配项时就显示这个路由页面。这几个页面我们可以随便写个组件都行,就像 上面配置 userCenter 中的 element 一样。但是为了美观,我事先设计 了几个页面直接引用也是一样的。

现在路由配置好了,那么我们就要在 SideMenuTest中做一点小小的更改,把主页面展示区改成 Router 的占位符组件, 并配置点击事件。如下所示:

import VerticalSplitIcon from '@mui/icons-material/VerticalSplit';
import Box from '@mui/material/Box';
import SideMenu from "./SMenu/SideMenu";
import SToggleButton from './SMenu/_SToggleButton';
import { useSideMenuBadgeUpdate } from './SMenu/_SMenuHooks';
import FullPage from './SLayout/FullPage';
import Stack from '@mui/material/Stack';
import ToggleThemeButton from './STheme/TaggleThemeButton';
import { Outlet, useNavigate } from 'react-router-dom';function SideMenuTest() {const navigate = useNavigate();const updateBadge = useSideMenuBadgeUpdate();const onClickHandler = (id, title, idPath, titlePath) => {console.log(id, title, idPath, titlePath);updateBadge(id, 0);navigate(idPath.join("/"), true);}return (<FullPagesideMenu={<SideMenutitle="侧边菜单测试系统"logo="/logo.png"hClick={() => { navigate("/", true); }}mClick={onClickHandler} />}pageHeader={<Stackdirection="row"justifyContent="space-between"alignItems="center"spacing={2}className='w-100'><SToggleButton icon={<VerticalSplitIcon />} /><ToggleThemeButton /></Stack>}><Box className="w-100 h-100 d-flex flex-grow-1 justify-content-center align-items-center"><Outlet /></Box></FullPage>)
}export default SideMenuTest;

现在我们的效果应该是这样的:

在这里插入图片描述

相当的完美是不是。 至此,你只要多加练习,就一定能熟练的掌握 React 。本教程到此全部结束。

关于我的计划

快要过年了,事比较多,时间实在抽不出来了。可能要停更好几天了。后面我会出一个系列的 Swift UI 的教程和PHP相关的教程。祝大家新年快乐,万事如意。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/451912.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vcruntime140.dll有什么作用?vcruntime140.dll缺失的解决方法分享

解决因缺少vcruntime140.dll文件引起的问题实际上是相对简单的尽管最近有许多人在抱怨该文件频繁丢失且不知道该如何处理。作为一个责任编辑&#xff0c;我认为有很大的必要向大家清楚地解释一下。让我们从探索vcruntime140.dll文件缺少的修复方法吧。 一.msvcp140.dll的作用 …

计算机毕业设计 | vue+springboot 教务管理系统(附源码)

1&#xff0c;项目背景 随着我国高等教育的发展&#xff0c;数字化校园将成为一种必然的趋势&#xff0c;国内高校迫切需要提高教育工作的质量与效率&#xff0c;学生成绩管理工作是高校信息管理工作的重要组成部分&#xff0c;与国外高校不同&#xff0c;他们一般具有较大规模…

MySQL集群 1主1从 主从复制(原理 及配置命令)

CSDN 成就一亿技术人&#xff01; 今天分享一期 MySQL集群方案&#xff1a;主从集群 也是最常用的一种 CSDN 成就一亿技术人&#xff01; 目录 使用主从复制的原因&#xff08;优点&#xff09; 主从复制的过程&#xff08;原理&#xff09; 了解两大线程&#xff08; I/O…

1Panel应用推荐:青龙定时任务管理平台

1Panel&#xff08;github.com/1Panel-dev/1Panel&#xff09;是一款现代化、开源的Linux服务器运维管理面板&#xff0c;它致力于通过开源的方式&#xff0c;帮助用户简化建站与运维管理流程。为了方便广大用户快捷安装部署相关软件应用&#xff0c;1Panel特别开通应用商店&am…

MCP4725使用教程

1.前言 前面画的AD/DA的板子到了&#xff0c;早上刚刚焊接完成&#xff0c;于是就开始写程序了。原本想看一下网上的教程&#xff0c;但是真的找不到好教程&#xff0c;没办法只能自己翻手册去慢慢啃了。这不调试完毕了吗&#xff0c;于是就写一篇文章吧&#xff0c;也相当于给…

从 20 多套 MySQL 到 1 套 TiDB丨骏伯网络综合运营管理平台应用实践

原文来源&#xff1a; https://tidb.net/blog/a38c72a4 本文作者&#xff1a;骏伯网络 唐帆&#xff0c;PingCAP 贺美存 骏伯网络简介 广州骏伯网络是一家以数据驱动的科技公司&#xff0c;聚焦移动互联网营销服务&#xff0c;坚持以客户为中心&#xff0c;深耕 APP、运营…

Python对日期的一些操作

1. 把这种日期 Mon Jan 29 11:10:49 0800 2024 转换成 ‘2024/2/1 10:50:38’ 这里定义一个func 传入英文日期&#xff0c;返回标准日期格式 def time_formater(input_time_str): input_format %a %b %d %H:%M:%S %z %Y output_format %Y-%m-%d %H:%M:%S return dat…

STL篇三:list

文章目录 前言1.list的介绍和使用1.1 list的介绍1.2 list的使用1.3 list的迭代器的失效 2.list的模拟实现2.1 结点的封装2.2 迭代器的封装2.2.1 正向迭代器2.2.2 反向迭代器 2.3 list功能的实现2.3.1 迭代器的实例化及begin()、end() 2.3.2 构造函数2.3.3 赋值运算符重载2.3.4 …

字节跳动推出超高清文生视频模型,效果比Gen-2更强!

字节跳动的研究人员开发了一种超高清文生视频模型MagicVideo-V2。 MagicVideo-V2公布的实验评测数据显示&#xff0c;视频的高清度、润滑度、连贯性、文本语义还原等方面&#xff0c;比目前主流的文生视频模型Gen-2、Stable Video Diffusion、Pika 1.0等更出色。 这是因为&am…

Quartus IP学习之ISSP(In-System Sources Probes)

一、ISSP IP概要&#xff1a; ISSP&#xff1a;In-System Sources & Probes Intel FPGA IP 作用&#xff1a; 分为In-System Sources与In-System Probesn-System Sources&#xff0c;输入端&#xff0c;等价于拨码开关&#xff0c;通过输入板载FPGA上的拨码开关状态改变…

SpringBoot整合Flowable最新教程(二)启动流程

介绍 文章主要从SpringBoot整合Flowable讲起&#xff0c;关于Flowable是什么&#xff1f;数据库表解读以及操作的Service请查看SpringBoot整合Flowable最新教程&#xff08;一&#xff09;&#xff1b;   其他说明&#xff1a;Springboot版本是2.6.13&#xff0c;java版本是1…

go消息队列RabbitMQ - 订阅模式-direct

1.发布订阅 在Fanout模式中&#xff0c;一条消息&#xff0c;会被所有订阅的队列都消费。但是&#xff0c;在某些场景下&#xff0c;我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。 在Direct模型下&#xff1a; 队列与交换机的绑定&#xff0c;不能…