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

我们继续未完的课程。

我们已经设计完所有theme的有关逻辑和代码了。接下来就是菜单部分,首先,菜单分为菜单头和菜单列表,还有收缩模式和缩略模式。为配置能用化的考虑,我们在菜单配置方面采用了 Json 数组。而菜单本身的数据状态和App的业务逻辑是没有关联的。所以我们尽可能的把两者隔离开。组件间的状态共享一般通过 Props 、state、 及Reducer 这么种方式。对于单层状态的上下传递我们采用 Props 和 state 就可以,但对于多层级的状传递这种方式就很不合适了。我们一般采用 Reducer 来管理组件的状态。说到Reducer ,一个是 React Redux , 一个是React本身中的Recuder功能。Redux是重量级的,用于整合App的业务逻辑部分是最合适不过的。但是对于那么细化的封闭的组合Reducer就更加合适了。对于这个SMenu组件,我们采用 Reducer 来完成整个组件的状态的管理。

菜单配置数据的设计

我们在SMenu目录下创建 menuData.jsx 文件

import DataUsageIcon from '@mui/icons-material/DataUsage';
import PersonIcon from '@mui/icons-material/Person';
import GroupAddIcon from '@mui/icons-material/GroupAdd';
import VerifiedUserIcon from '@mui/icons-material/VerifiedUser';
import FeaturedVideoIcon from '@mui/icons-material/FeaturedVideo';
import PasswordIcon from '@mui/icons-material/Password';
import VpnKeyIcon from '@mui/icons-material/VpnKey';
import HealthAndSafetyIcon from '@mui/icons-material/HealthAndSafety';
import ReplyAllIcon from '@mui/icons-material/ReplyAll';//菜单的测试数据
const sideMenuConfigData = [{ id: "init", title: "系统初始化", icon: DataUsageIcon },{ id: "management", title: "用户管理", icon: GroupAddIcon },{id: "userMsg", title: "角色管理", icon: PersonIcon, children: [{ id: "", title: "权限管理", icon: VerifiedUserIcon },{ id: "pwdMsg", title: "密码管理", icon: PasswordIcon },{ id: "keyMsg", title: "私钥管理", icon: VpnKeyIcon },{ id: "agentMsg", title: "权限管理", icon: HealthAndSafetyIcon },]},{ id: "advMsg", title: "广告管理", icon: FeaturedVideoIcon },{ id: "plyMsg", title: "评论管理", icon: ReplyAllIcon },{id: "title", title: "文章管理", icon: null, children: [{ id: "caogaoMsg", title: "草稿件", icon: null },{ id: "newFile", title: "新建文章", icon: null },{ id: "firstMsg", title: "置顶管理", icon: null },{ id: "recMsg", title: "推荐管理", icon: null },{ id: "classMsg", title: "类型管理", icon: null },{ id: "emailMsg", title: "邮箱管理", icon: null },]},{ id: "system", title: "系统设置", icon: null },{ id: "userCenter", title: "个人中心", icon: null }
];export default sideMenuConfigData;

设定:为了最大化的保证菜单的格调和美观,我们菜单最大支持到二级菜单。菜单支持 badge 数字提醒功能, 支持图标。为了设计上的统一,图标一定要是MUI的图标,其它svg要通过 MUIcreateSvgIcon 函数进行封装才能用于本菜单的配置。通过上面的配置可以看出,组菜单有 children 项。没有这一属性的就是一级菜单。很容易分别。

我们在 SMenu 项目目录下再健一个目录 SMenu菜单目录, 我取了一个同名的目录名称。用这个目录来存放SMenu的所有子组件。

创建菜单Recucer数据

我们在SMenu菜单目录下创建一个Provider文件:SideMenuProvider.jsx, 我们将有关的初始状态值及相关的Context 都放到这个文件 里,如下所示:

// SideMenuProvider.jsx
import { useReducer, createContext, useState } from 'react';/*** 获取菜单项的id集合, 用于初始化菜单项的徽章,本菜单的每个Item都有一个id属性,用于唯一标识菜单项。* @param menuConfig * @returns */
function initBadge(menuConfig){let ids = {};menuConfig.forEach((element) => {const name = element.id;ids = { ...ids, [name]: 0 };if (element.children) {const children = element.children;children.forEach(el => {const subName = el.id;ids = { ...ids, [subName]: 0 };})}});return ids;
}//菜单的内部状态的初始值,用react的reducer来管理, 用context来向子组件传递通信。
const initState = {activeItemId: null, //当点击一个菜单项时记录活动菜单项hoverItemId: null, //当点击一个菜单项组标题时,记录打开的GroupMenu的名称。open: true, //菜单项的展开模式,true为展开,false为折叠showDivider: true, //菜单项的分割线模式,true为显示,false为不显示
}const reducer = (state, action) => {return {...state,...action}
}export const SideMenuState = createContext(initState); //菜单的内部状态
export const SideMenuBadge = createContext(null); //菜单的徽章配置数据
export const DispatchMenuState = createContext(null); //菜单的内部状态的更新函数
export const DispatchMenuBadge = createContext(null); //菜单的徽章的更新函数
export const SideMenuData = createContext([]); //菜单的配置数据/*** 菜单的上下文Context* @param children * @param menuData * @returns */
function SideMenuProvider({ children, menuData }) {const [badge, updateBadge] = useState(initBadge(menuData));const [menuState, updateMenuState] = useReducer(reducer, initState);const updateBadgeHandler = (id, count) => {updateBadge((state) => {return {...state,[id]: count}})}return (<SideMenuState.Provider value={ menuState }><SideMenuBadge.Provider value={badge}><DispatchMenuState.Provider value={updateMenuState}><DispatchMenuBadge.Provider value={updateBadgeHandler}><SideMenuData.Provider value={menuData}>{children}</SideMenuData.Provider></DispatchMenuBadge.Provider></DispatchMenuState.Provider></SideMenuBadge.Provider></SideMenuState.Provider>)
}export default SideMenuProvider;

你看,我们在设计Theme的时候用的方法在这里又一次使用了。文件中我都做了想关说明了,一看就能明白。是不是很顺手。我们设计了众多的Context, 那么我们就要提供相应的 Hook 使得我们可以在组件内部调用这些值。所以我们在相同的目录下再创建一个Hooks工具库:_SMenuHooks.jsx

// _SMenuHooks.jsximport { useContext } from 'react';
import { DispatchMenuBadge, DispatchMenuState, SideMenuBadge, SideMenuData, SideMenuState } from './SideMenuProvider'; // 获取边栏菜单的状态
export function useSideMenuState() {return useContext(SideMenuState);
}// 获取边栏菜单的小红点状态
export function useSideMenuBadge() {return useContext(SideMenuBadge);
}// 更新边栏菜单小红点的工具,用法:
// const update = useSideMenuBadgeUpdate();
// update("menuItemId", 50)
export function useSideMenuBadgeUpdate() {return useContext(DispatchMenuBadge);
}// 更新边栏菜单工具
export function useSideMenuStateUpdate() {return useContext(DispatchMenuState);
}// 获取菜单配置项
export function useSideMenuData() {return useContext(SideMenuData);
}

至此,这个Provider就创建完了。我们在SMenu项目目录下创建一个App.jsx做为这个示例的入口文件:

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

我们姑且先用 <SideMenuTest />组件来代表这个测试工程,先不用管它。或者留空又或者随便写点啥都行。现在再次回到菜单目录 SMenu,我们开始对菜单的组件进行设计

菜单头

创建 _SideMenuHeader.jsx 文件

import Box from '@mui/system/Box';
import Avatar from '@mui/material/Avatar';
import Typography from '@mui/material/Typography';
import Stack from '@mui/system/Stack';
import { useSideMenuState } from './_SMenuHooks';
import { redirect } from 'react-router-dom';//菜单头
const SideMenuHeader = ({logo, //图标title, //标题onClick //单击事件
}) => {const { open } = useSideMenuState();const clickEvent = () => {if (onClick == null) {redirect("/");} else {onClick();console.log("clickEvent");}}return (<Box className="p-3 border-bottom" ><Stackspacing={2}direction={"row"}justifyContent="start"alignItems={"center"}className="w-100"><Avatarsx={{width: 35,height: 35,cursor: "pointer",transition: '0.2s',transform: open ? 'scale(1)' : 'scale(1.2)',}}src={logo}variant="rounded"alt={title}onClick={clickEvent}>{title && title.substring(0, 1).toUpperCase()}</Avatar><Typography className="text-truncate" variant="h5" sx={{pl: 0.5}} > { title ||  "码蚁基地" } </Typography></Stack></Box>)
};export default SideMenuHeader;

组件内 className 应用的就是Bootstrap的样式, sxMui style 的封装。 组件 SideMenuHeader接收一个 logo文件地址、标题、和一个点击事件的回调。Logo 如果为空则以 标题的第一个字为 Logo图像。点击回调是赋于Logo的点击事件的。

数据提醒徽章

这个功能是用来显示消息的红点提示,有两种方案,一个是显示一个小红点,一个是显示数字。大于99的显示 99+的徽章。为了更好的适配菜单,我们用 styled 函数对 Badge 进行了二次封。如下所示,创建 _SideMenuStyledBadge.jsx

// _SideMenuStyledBadge.jsximport { styled } from '@mui/material/styles';
import Badge from '@mui/material/Badge';const StyledBadge = styled(Badge)(({ theme }) => ({'& .MuiBadge-badge': {right: -22,top: 16,// border: `2px solid ${theme.palette.background.paper}`,padding: '0 4px',},
}));export default StyledBadge;
一级菜单项

就是没有子菜单项的菜单项, 创建文件 _SideMenuItem.jsx

import Tooltip from '@mui/material/Tooltip';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import Avatar from '@mui/material/Avatar';
import SvgIcon from '@mui/material/SvgIcon';
import { useSideMenuBadge, useSideMenuState, useSideMenuStateUpdate } from './_SMenuHooks';
import StyledBadge from './_SideMenuStyledBadge';
import Badge from '@mui/material/Badge';
import { grey } from '@mui/material/colors';/*** 主菜单项组件* @param title: 菜单项标题* @param id: 菜单项ID* @param icon: 菜单项图标* @param onClick: 菜单项单击事件 * @returns */
const SideMenuItem = ({title, id,icon = null,onClick,
}) => {const {activeItemId, open} = useSideMenuState();const badgeCount = useSideMenuBadge();const updateMenuState = useSideMenuStateUpdate();//单击事件const itemClickeEvent = () => {updateMenuState({ activeItemId: id });onClick(id, title, [id], [title]);}return (<ListItemButtonselected={ activeItemId == id }onClick={itemClickeEvent}><Tooltip title={open ? null : title} arrow placement="right"><BadgebadgeContent={open ? 0 : badgeCount[id]}anchorOrigin={{vertical: 'top',horizontal: 'left',}}color="error"><ListItemIconsx={{'& svg': {transition: '0.2s',transform: open ? 'scale(1)' : 'scale(1.2)',},'&:hover, &:focus': {'& svg:first-of-type': {transform: open ? 'scale(1)' : 'scale(1.3)',}},}}>{icon == null ? <Avatarsx={{width: 30,height: 30,fontSize: 18,bgcolor:grey[700],transition: '0.2s',transform: open ? 'scale(1)' : 'scale(1.2)'}}variant="rounded">{title.substring(0, 1).toUpperCase()}</Avatar> :<SvgIcon component={icon} />}</ListItemIcon></Badge></Tooltip><StyledBadge badgeContent={badgeCount[id]} color="error"><ListItemText primary={title}/></StyledBadge></ListItemButton>);
};export default SideMenuItem;
组菜单的子菜单项

二级菜单的子菜单项的组件设计 ,创建文件 _SideMenuSubItem.jsx

// _SideMenuSubItem.jsximport ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import Typography from '@mui/material/Typography';
import Avatar from '@mui/material/Avatar';
import Tooltip from '@mui/material/Tooltip';
import Badge from '@mui/material/Badge';
import SvgIcon from '@mui/material/SvgIcon';
import CssBaseline from '@mui/material/CssBaseline';
import StyledBadge from './_SideMenuStyledBadge';import { useSideMenuBadge, useSideMenuState, useSideMenuStateUpdate } from './_SMenuHooks';/*** 子菜单项组件* @param icon: 菜单项图标* @param title: 菜单项标题* @param id: 菜单项ID* @param groupId: 菜单项组ID* @param groupTitle: 菜单项组标题* @param onClick: 菜单项单击事件 * @returns */
function SideMenuSubItem({icon = null,title,id,groupId,groupTitle,onClick
}) {const { activeItemId, open } = useSideMenuState();const updateMenuState = useSideMenuStateUpdate();const badgeCount = useSideMenuBadge();const handleClick = () => {updateMenuState({ activeItemId: id });onClick(id, title, [groupId, id], [groupTitle, title])};return (<ListItemButtononClick={handleClick}selected={ activeItemId == id }sx={{transition: "padding 0.3s",pl: open ? 5 : 2.5,}}><CssBaseline /><Tooltip title={open ? null : title} arrow placement="right"><BadgebadgeContent={open ? 0 : activeItemId === groupId ? 0 : badgeCount[id]}anchorOrigin={{vertical: 'top',horizontal: 'left',}}color="error"><ListItemIconsx={{'& svg': {transition: '0.2s',transform: open ? 'scale(1)' : 'scale(1.2)',},'&:hover, &:focus': {'& svg:first-of-type': {transform: open ? 'scale(1)' : 'scale(1.3)',}},}}>{icon == null ?<Avatarsx={{width: 24,height: 24,fontSize: 16,transition: '0.2s',transform: open ? 'scale(1)' : 'scale(1.2)',}}variant="rounded"> {title.substring(0, 1).toUpperCase()} </Avatar> :<SvgIcon component={icon} sx={{ fontSize: 16 }} />}</ListItemIcon></Badge></Tooltip><StyledBadge badgeContent={badgeCount[id]} color="error"><ListItemTextprimary={<Typographysx={{ display: 'inline' }}component="span"variant="body1"color="text.secondary">{title}</Typography>}/></StyledBadge></ListItemButton>);
}export default SideMenuSubItem;
菜单组

我们现这个子菜单项与 菜单级合并,形成一个菜单组项,创建文件:_SideMenuGroup.jsx

// _SideMenuGroup.jsximport React from 'react';
import List from '@mui/material/List';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import Collapse from '@mui/material/Collapse';
import ExpandLess from '@mui/icons-material/ExpandLess';
import ExpandMore from '@mui/icons-material/ExpandMore';
import Avatar from '@mui/material/Avatar';
import Badge from '@mui/material/Badge';
import Tooltip from '@mui/material/Tooltip';
import SvgIcon from '@mui/material/SvgIcon';
import StyledBadge from './_SideMenuStyledBadge';
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import { grey } from '@mui/material/colors';import { useSideMenuState, useSideMenuStateUpdate, useSideMenuBadge } from './_SMenuHooks';
import SMenuSubItem from './_SideMenuSubItem';function IconItem ({ open, icon, title }) {return (<ListItemIconsx={{'& svg': {transition: '0.2s',transform: open ? 'scale(1)' : 'scale(1.2)',},'&:hover, &:focus': {'& svg:first-of-type': {transform: open ? 'scale(1)' : 'scale(1.3)',}},}}>{icon == null ?<Avatarsx={{width: 30,height: 30,fontSize: 18,bgcolor: grey[600],transition: '0.2s',transform: open ? 'scale(1)' : 'scale(1.2)'}}variant="rounded">{title.substring(0, 1).toUpperCase()}</Avatar> :<SvgIcon component={icon} />}</ListItemIcon>)
}/*** 含有子菜单的菜单项* @param props * @returns */
function SideMenuGroup({id, //菜单项的ID名称icon = null, //图标title, //标题childrenData, //子菜单 onClick, //单击事件
}) {const { hoverItemId, open } = useSideMenuState();const updateMenuState = useSideMenuStateUpdate();const badgeCount = useSideMenuBadge();const groupBadgeNumber = childrenData.map((item) => badgeCount[item.id]).reduce((a, b) => a + b, 0); const handleClick = () => {updateMenuState({hoverItemId: hoverItemId === id ? null : id})};return (<Box><ListItemButton onClick={handleClick}><Tooltip title={open ? null : title} arrow placement="right"><BadgebadgeContent={open ? 0 : hoverItemId === id ? 0 : groupBadgeNumber}anchorOrigin={{vertical: 'top',horizontal: 'left',}}// variant="dot"color="error"><IconItem open={open} icon={icon} title={title} /></Badge></Tooltip><Stack direction={"row"} justifyContent={"space-between"} sx={{ width: 300 }}><StyledBadge badgeContent={ hoverItemId === id ? null : groupBadgeNumber } color="error"><ListItemText primary={title} /></StyledBadge>{hoverItemId === id ? <ExpandLess /> : <ExpandMore />}</Stack></ListItemButton><Collapse in={ hoverItemId === id } timeout="auto" unmountOnExit><List component="div" dense={true} disablePadding>{childrenData === undefined ? null :childrenData.map(function (itemData, index) {return <SMenuSubItemicon = { itemData.icon }title = { itemData.title }id = {itemData.id}groupId = {id}groupTitle={title}onClick={onClick}key={index} />})}</List></Collapse></Box>);
}export default SideMenuGroup;

注意,菜单组的 Badge 显示是通过计数子菜单的 badeg 来显示的,尽管我们在 Badge Context 中有配置,但组菜单的这个配置是不启作用的。所以上面就有了这个统计的设计:

const groupBadgeNumber = childrenData.map((item) => badgeCount[item.id]).reduce((a, b) => a + b, 0); 
收缩按钮的设计

这里我设计了一个收缩菜单的按钮,你可以把它放在任何地方,不一定是在菜单组件内,可以是在整个 App 应用的任何地方都行, 创建文件:_SToggleButton.jsx

import IconButton from '@mui/material/IconButton';
import { useSideMenuState, useSideMenuStateUpdate } from './_SMenuHooks';/*** 菜单的展开/收起按钮* @param {*} param0 * @returns */
function SToggleButton({icon}) {const menuState = useSideMenuState();const updateMenuState = useSideMenuStateUpdate();const clickHandler = () => {updateMenuState({ open: !menuState.open})}return (<IconButton onClick={clickHandler}>{ icon }</IconButton>)
}export default SToggleButton;
整合所有组件

现 在就是整合所有的组件了。创建文件 SideMenu.jsx ,我一般内部组件的文件名前加一个下划线,以示区分,封装好的组件则不加下划线:

// SideMenu.jsximport Box from '@mui/system/Box';
import SideMenuItem from './_SideMenuItem';
import Divider from '@mui/material/Divider';
import SideMenuGroup from './_SideMenuGroup';
import { useSideMenuData, useSideMenuState } from './_SMenuHooks';
import { List } from '@mui/material';
import SideMenuHeader from "./_SideMenuHeader";/*** 菜单的主体组件* * @returns */
function SideMenu({title,logo,hClick,mClick,footer,
}) {const menuData = useSideMenuData();const { open } = useSideMenuState();const openWidth = 300;const minWidth = 65;return (<BoxclassName="d-flex overflow-hidden h-100"elevation={1}sx={{transition: "width 0.3s",width: open ? openWidth : minWidth,borderRight: 1,borderColor: "divider",}}>        <Box className='d-flex flex-column'><SideMenuHeadertitle={title}logo={logo}onClick={hClick}/><Boxsx={{flex: 1,overflowY: "auto",overflowX: "hidden",width: open ? openWidth : minWidth,}}><List sx={{width: openWidth}}>                    { menuData.map((item, index) => {const subItemsData = item.children || null;if (subItemsData == null) {return <SideMenuItemid={item.id}title={item.title}icon={item.icon}onClick={mClick}key={index}/>}return <SideMenuGroupicon={item.icon}id={item.id}title={item.title}childrenData={item.children}onClick={mClick}key={index} />})}</List></Box>{footer == null ?null :<><Divider />{footer}</>}</Box></Box>);
}export default SideMenu;

大功告成。菜单组件全部设计完成。那么如何应用呢,我们下章详解。

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

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

相关文章

uniapp基于Android的环境保护环保商城系统生活垃圾分类 小程序_rsj68

本环境保护生活App是为了提高用户查阅信息的效率和管理人员管理信息的工作效率&#xff0c;可以快速存储大量数据&#xff0c;还有信息检索功能&#xff0c;这大大的满足了用户和管理员这两者的需求。操作简单易懂&#xff0c;合理分析各个模块的功能&#xff0c;尽可能优化界面…

WPF布局面板

StackPanel StackPanel 是一种常用的布局控件,可以支持水平或垂直排列,但不会换行。当子元素添加到 StackPanel 中时,它们将按照添加的顺序依次排列。默认情况下,StackPanel 的排列方向是垂直的,即子元素将从上到下依次排列。可以使用 Orientation 属性更改排列方向。可以…

Apache POI与easyExcel:Excel文件导入导出的技术深度分析

在处理Excel文件时&#xff0c;Java开发者经常会面临多种选择&#xff0c;其中Apache POI和easyExcel是两个非常受欢迎的选择。这两个库都提供了强大的Excel文件处理功能&#xff0c;但在性能、内存使用、API设计以及扩展性方面有所不同。本文将深入分析Apache POI和easyExcel在…

开发中小程序遇到的问题总结

1. backdrop-filter样式的作用 backdrop-filter 是CSS中的一个属性&#xff0c;用于为元素的背景区域添加图形效果&#xff0c;如模糊或者颜色偏移。这个属性的使用需要满足一定的条件&#xff0c;即元素本身或者其背景至少部分必须是透明的&#xff0c;这样才能让附加的效果显…

Unity 通过配置文件生成代码

文章目录 示例1&#xff1a;基于ScriptableObject的配置生成类示例2&#xff1a;预制体路径列表生成加载代码示例3&#xff1a;动画剪辑生成动画控制器片段示例4&#xff1a;Excel配置表生成序列化类示例5&#xff1a;UI元素及其事件绑定生成代码 在Unity编辑器模式下&#xff…

【BBF系列协议】TR181-2 TR369的设备数据模型

针对CWMP端点和USP代理的TR-181设备数据模型 执行摘要 TR-181问题2定义了设备数据模型的版本2(设备:2)。设备:2数据模型适用于所有类型的TR-069或USP启用的设备,包括终端设备、住宅网关和其他网络基础设施设备。 本技术报告中定义的设备:2数据模型由一组数据对象组成,…

电商实战练习部署

基于阿里云ECS服务器实战部署 1 单架构部署方案 1.1 部署流程 传统方案 基于docker 2 持续集成&持续部署方案 随着软件开发复杂度的不断提高&#xff0c;团队开发成员间如何更好地协同工作以确保软件 开发的质量已经慢慢成为开发过程中不可回避的问题。互联网软件的开发…

护眼台灯有aaa级吗为什么?一文揭晓护眼台灯照度等级分类

尽管台灯是一个很成熟的行业&#xff0c;但却时不时也会冒出一些新的概念和名词。比如近些年的”AAA级”台灯&#xff0c;很频繁地出现在我们视野中。给人感觉似乎带”AAA级”的台灯&#xff0c;要比其他的强上一头。那到底是真是假呢&#xff1f; 一、护眼台灯有AAA级吗&…

字节跳动推出MagicVideo-V2超高清文生视频模型

&#x1f989; AI新闻 &#x1f680; 字节跳动推出MagicVideo-V2超高清文生视频模型 摘要&#xff1a;MagicVideo-V2是由字节跳动的研究人员开发的一种超高清文生视频模型。该模型在视频的高清度、润滑度、连贯性、文本语义还原等方面表现出色&#xff0c;比目前主流的文生视…

leetcode 1.两数之和(C++)DAY1(待补充哈希表法)

文章目录 1.题目描述示例提示 2.解答思路3.实现代码结果4.总结 1.题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&…

ffmpeg操作实战001:视频+音频文件融合

一、功能需求 把视频文件video.mp4 和音频文件audio.wav融合在一起&#xff0c;输出视频文件output.mp4 二、操作指令 ffmpeg -i video.mp4 -i audio.wav -c:v copy -map 0:v:0 -map 1:a:0 output.mp4 三、参数说明 ffmpeg: 这是用于执行FFmpeg命令行工具的命令。-i video…

04. 【Linux教程】安装 Linux 操作系统

通过前面的小节学习&#xff0c;我们已经对 Linux 操作系统有了简单的了解&#xff0c;同时也在 Windows 下安装了虚拟机软件 VMware &#xff0c;那么本节课我们就介绍下如何使用虚拟机软件安装 Linux 操作系统。 通过第一小节的学习我们知道 Linux 有很多的发行版本&#xf…

Spring Data JpaRepository数据库增、删、改、查接口快速实现

1. Controller&#xff08;EventController.java&#xff09; RestController RequestMapping("/Event") public class EventController {// 案件信息AutowiredEventRepository eventRepository;// 添加、编辑PostMapping("/addEvent")public ResponseObj…

工信部颁发的《计算机视觉处理设计开发工程师》中级证书

计算机视觉&#xff08;Computer Vision&#xff09;是一门研究如何让计算机能够理解和分析数字图像或视频的学科。简单来说&#xff0c;计算机视觉的目标是让计算机能够像人类一样对视觉信息进行处理和理解。为实现这个目标&#xff0c;计算机视觉结合了图像处理、机器学习、模…

主从不一致解决方案

此方案重新实现主从,数据完全同步 1)进入主库数据库 mysql -uroot -proot 2) 在主库加锁,开启只读服务(保证没有新数据写入) flush tables with read lock; 3)在主库进行数据备份,把数据备份为.sql的文件 mysqldump -u登陆用户 -p登陆密码 --all-databases > my…

11.3 Web开发_JavaScript入门(❤❤❤)

11.3 Web开发_JavaScript入门 1. 简介1.1 JavaScript简介1.2 浏览器执行js1.3 js组成1.4 js书写位置2. 基础语法2.1 变量2.2 数据类型2.3 数据类型检测_typeof ❤❤2.4 NaN 和 isNaN2.5 数据类型相互转换3. 运算符及流程控制3.1 运算符3.2 流程控制1. 分支结构 if..

Python 连接 mysql 详解(mysql-connector-python)

文章目录 1 概述1.1 第三方库&#xff1a;mysql-connector-python1.2 可视化工具&#xff1a;navicat1.3 创建测试数据库 2 连接 mysql 数据库2.1 创建一个连接2.2 捕获连接异常2.3 从配置文件中获取连接信息 3 执行 sql 语句3.1 插入、更新、删除3.2 查询 1 概述 1.1 第三方库…

深度学习系列56:使用whisper进行语音转文字

1. openai-whisper 这应该是最快的使用方式了。安装pip install -U openai-whisper&#xff0c;接着安装ffmpeg&#xff0c;随后就可以使用了。模型清单如下&#xff1a; 第一种方式&#xff0c;使用命令行&#xff1a; whisper japanese.wav --language Japanese --model…

前端Vue every() 方法

every() 方法用于检测数组所有元素是否都符合指定条件&#xff08;通过函数提供&#xff09;。 every() 方法使用指定函数检测数组中的所有元素&#xff1a; 如果数组中检测到有一个元素不满足&#xff0c;则整个表达式返回 false &#xff0c;且剩余的元素不会再进行检测。如…

网易和腾讯面试题精选---性能和优化面试问题

介绍 在当今快节奏的数字环境中,优化性能对于确保软件系统的效率、可靠性和可扩展性至关重要。随着组织努力提供无缝的用户体验、满足不断增长的需求并保持竞争力,性能调整和优化成为关键学科。本文深入探讨了跨不同领域、技术和应用场景优化系统性能的关键策略、技术和最佳…