📜  如何在 ReactJS 中创建带有下拉菜单的响应式侧边栏?

📅  最后修改于: 2022-05-13 01:56:25.993000             🧑  作者: Mango

如何在 ReactJS 中创建带有下拉菜单的响应式侧边栏?

侧边栏是网站设计的重要元素,因为它允许用户快速访问网站中的任何部分。

项目概览:

先决条件:

  1. npm
  2. 创建反应应用
  3. 反应路由器dom
  4. useState React 钩子

基本设置:您将使用create-react-app启动一个新项目,因此打开终端并输入:

npx create-react-app react-sidebar-dropdown

现在通过在终端中输入给定的命令转到您的react-sidebar-dropdown文件夹:

cd react-sidebar-dropdown

所需模块:通过在终端中键入给定命令来安装此项目所需的依赖项。

npm install react-router-dom
npm install --save styled-components
npm install --save react-icons

现在在 src 中创建components文件夹,然后转到 components 文件夹并创建三个文件Sidebar.jsSidebarData.jsSubMenu.js

在 src 中创建一个名为pages的文件夹,并在 pages 中创建名为AboutUs.jsContactUs.jsEvents.jsServices.jsSupport.js的文件。

项目结构:项目中的文件结构将如下所示。

Filename- Sidebar.js:打开和关闭侧边栏视图,这就是useState( )钩子发挥作用的地方。

我们创建一个状态,第一个元素侧边栏作为初始状态,其值为 false,第二个元素作为函数setSidebar()用于更新状态。然后创建一个名为showSidebar( ) 的函数,该函数在调用时将侧边栏的值设置为与其当前值相反。

此函数在onClick()函数的帮助下与菜单栏图标和十字图标一起使用。当我们单击条形图标以查看 sidenav 链接时,它将状态的值设置为 true,显示侧边栏,并在条形图标的位置出现一个十字图标。当我们想要关闭侧边栏时,我们只需单击十字图标,在关闭侧边栏后它会被一个条形图标替换,因为现在状态的值设置为 false。

Javascript
import React, { useState } from "react";
import styled from "styled-components";
import { Link } from "react-router-dom";
import * as FaIcons from "react-icons/fa";
import * as AiIcons from "react-icons/ai";
import { SidebarData } from "./SidebarData";
import SubMenu from "./SubMenu";
import { IconContext } from "react-icons/lib";
  
const Nav = styled.div`
  background: #15171c;
  height: 80px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;
  
const NavIcon = styled(Link)`
  margin-left: 2rem;
  font-size: 2rem;
  height: 80px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;
  
const SidebarNav = styled.nav`
  background: #15171c;
  width: 250px;
  height: 100vh;
  display: flex;
  justify-content: center;
  position: fixed;
  top: 0;
  left: ${({ sidebar }) => (sidebar ? "0" : "-100%")};
  transition: 350ms;
  z-index: 10;
`;
  
const SidebarWrap = styled.div`
  width: 100%;
`;
  
const Sidebar = () => {
  const [sidebar, setSidebar] = useState(false);
  
  const showSidebar = () => setSidebar(!sidebar);
  
  return (
    <>
      
        
        
          
            
              
            
            {SidebarData.map((item, index) => {
              return ;
            })}
          
        
      
    
  );
};
  
export default Sidebar;


Javascript
import React from "react";
import * as FaIcons from "react-icons/fa";
import * as AiIcons from "react-icons/ai";
import * as IoIcons from "react-icons/io";
import * as RiIcons from "react-icons/ri";
  
export const SidebarData = [
  {
    title: "About Us",
    path: "/about-us",
    icon: ,
    iconClosed: ,
    iconOpened: ,
  
    subNav: [
      {
        title: "Our Aim",
        path: "/about-us/aim",
        icon: ,
      },
      {
        title: "Our Vision",
        path: "/about-us/vision",
        icon: ,
      },
    ],
  },
  {
    title: "Services",
    path: "/services",
    icon: ,
    iconClosed: ,
    iconOpened: ,
  
    subNav: [
      {
        title: "Service 1",
        path: "/services/services1",
        icon: ,
        cName: "sub-nav",
      },
      {
        title: "Service 2",
        path: "/services/services2",
        icon: ,
        cName: "sub-nav",
      },
      {
        title: "Service 3",
        path: "/services/services3",
        icon: ,
      },
    ],
  },
  {
    title: "Contact",
    path: "/contact",
    icon: ,
  },
  {
    title: "Events",
    path: "/events",
    icon: ,
  
    iconClosed: ,
    iconOpened: ,
  
    subNav: [
      {
        title: "Event 1",
        path: "/events/events1",
        icon: ,
      },
      {
        title: "Event 2",
        path: "/events/events2",
        icon: ,
      },
    ],
  },
  {
    title: "Support",
    path: "/support",
    icon: ,
  },
];


Javascript
import React, { useState } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
  
const SidebarLink = styled(Link)`
  display: flex;
  color: #e1e9fc;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  list-style: none;
  height: 60px;
  text-decoration: none;
  font-size: 18px;
  
  &:hover {
    background: #252831;
    border-left: 4px solid green;
    cursor: pointer;
  }
`;
  
const SidebarLabel = styled.span`
  margin-left: 16px;
`;
  
const DropdownLink = styled(Link)`
  background: #252831;
  height: 60px;
  padding-left: 3rem;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #f5f5f5;
  font-size: 18px;
  
  &:hover {
    background: green;
    cursor: pointer;
  }
`;
  
const SubMenu = ({ item }) => {
  const [subnav, setSubnav] = useState(false);
  
  const showSubnav = () => setSubnav(!subnav);
  
  return (
    <>
      
        
          {item.icon}           {item.title}         
        
          {item.subNav && subnav             ? item.iconOpened             : item.subNav             ? item.iconClosed             : null}         
      
      {subnav &&         item.subNav.map((item, index) => {           return (                            {item.icon}               {item.title}                        );         })}        ); };    export default SubMenu;


Javascript
import React from "react";
  
export const AboutUs = () => {
  return (
    
      

GeeksforGeeks About us

    
  ); };    export const OurAim = () => {   return (     
      

GeeksforGeeks Aim

    
  ); };    export const OurVision = () => {   return (     
      

GeeksforGeeks Vision

    
  ); };


Javascript
import React from "react";
  
const Contact = () => {
  return (
    
      

GeeksforGeeks Contact us

    
  ); };    export default Contact;


Javascript
import React from "react";
  
export const Events = () => {
  return (
    
      

GeeksForGeeks Events

    
  ); };    export const EventsOne = () => {   return (     
      

GeeksforGeeks Event1

    
  ); };    export const EventsTwo = () => {   return (     
      

GeeksforGeeks Event2

    
  ); };


Javascript
import React from "react";
  
export const Services = () => {
  return (
    
      

GeeksforGeeks Services

    
  ); };    export const ServicesOne = () => {   return (     
      

GeeksforGeeks Service1

    
  ); };    export const ServicesTwo = () => {   return (     
      

GeeksforGeeks Service2

    
  ); };    export const ServicesThree = () => {   return (     
      

GeeksforGeeks Service3

    
  ); };


Javascript
import React from "react";
  
const Support = () => {
  return (
    
      

GeeksforGeeks Support us

    
  ); };    export default Support;


Javascript
import "./App.css";
import Sidebar from "./components/Sidebar";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { AboutUs, OurAim, OurVision } from "./pages/AboutUs";
import {
  Services,
  ServicesOne,
  ServicesTwo,
  ServicesThree,
} from "./pages/Services";
import { Events, EventsOne, EventsTwo } from "./pages/Events";
import Contact from "./pages/ContactUs";
import Support from "./pages/Support";
function App() {
  return (
    
      
      
        
        
        
        
        
        
        
        
        
        
        
        
      
    
  );
}
  
export default App;


HTML
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
.home,
.services,
.reports,
.contact,
.events,
.support {
  display: flex;
  margin-left: 260px;
  font-size: 2rem;
}


文件名- SidebarData.js

Javascript

import React from "react";
import * as FaIcons from "react-icons/fa";
import * as AiIcons from "react-icons/ai";
import * as IoIcons from "react-icons/io";
import * as RiIcons from "react-icons/ri";
  
export const SidebarData = [
  {
    title: "About Us",
    path: "/about-us",
    icon: ,
    iconClosed: ,
    iconOpened: ,
  
    subNav: [
      {
        title: "Our Aim",
        path: "/about-us/aim",
        icon: ,
      },
      {
        title: "Our Vision",
        path: "/about-us/vision",
        icon: ,
      },
    ],
  },
  {
    title: "Services",
    path: "/services",
    icon: ,
    iconClosed: ,
    iconOpened: ,
  
    subNav: [
      {
        title: "Service 1",
        path: "/services/services1",
        icon: ,
        cName: "sub-nav",
      },
      {
        title: "Service 2",
        path: "/services/services2",
        icon: ,
        cName: "sub-nav",
      },
      {
        title: "Service 3",
        path: "/services/services3",
        icon: ,
      },
    ],
  },
  {
    title: "Contact",
    path: "/contact",
    icon: ,
  },
  {
    title: "Events",
    path: "/events",
    icon: ,
  
    iconClosed: ,
    iconOpened: ,
  
    subNav: [
      {
        title: "Event 1",
        path: "/events/events1",
        icon: ,
      },
      {
        title: "Event 2",
        path: "/events/events2",
        icon: ,
      },
    ],
  },
  {
    title: "Support",
    path: "/support",
    icon: ,
  },
];

Filename- SubMenu.js:下拉链接的逻辑,同样使用useState()钩子完成。

我们创建一个状态,第一个元素 subnav 作为初始状态,其值为 false,第二个元素作为函数setSubnav()用于更新状态。然后创建一个名为showSubnav()的函数,该函数在调用时将 subnav 的值设置为与其当前值相反。

此函数与打开图标和关闭图标一起使用。当我们单击打开图标查看下拉链接时,它会将状态值设置为 true,显示下拉菜单,并在打开图标的位置出现一个关闭图标。当我们想要关闭下拉链接时,我们只需单击关闭图标,然后在关闭下拉菜单后将其替换为打开图标,因为现在状态的值设置为 false。

由于每个sidelink 都没有下拉菜单,它首先检查sideline 是否具有从我们在SidebarData.js文件中创建的对象数组中定义的subNav 属性。如果该属性存在,则它执行上述逻辑,否则侧链接正常显示,没有任何打开和关闭图标。

Javascript

import React, { useState } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
  
const SidebarLink = styled(Link)`
  display: flex;
  color: #e1e9fc;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  list-style: none;
  height: 60px;
  text-decoration: none;
  font-size: 18px;
  
  &:hover {
    background: #252831;
    border-left: 4px solid green;
    cursor: pointer;
  }
`;
  
const SidebarLabel = styled.span`
  margin-left: 16px;
`;
  
const DropdownLink = styled(Link)`
  background: #252831;
  height: 60px;
  padding-left: 3rem;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #f5f5f5;
  font-size: 18px;
  
  &:hover {
    background: green;
    cursor: pointer;
  }
`;
  
const SubMenu = ({ item }) => {
  const [subnav, setSubnav] = useState(false);
  
  const showSubnav = () => setSubnav(!subnav);
  
  return (
    <>
      
        
          {item.icon}           {item.title}         
        
          {item.subNav && subnav             ? item.iconOpened             : item.subNav             ? item.iconClosed             : null}         
      
      {subnav &&         item.subNav.map((item, index) => {           return (                            {item.icon}               {item.title}                        );         })}        ); };    export default SubMenu;

现在我们完成了 components 文件夹,现在我们操作页面。在 src/pages 中编辑项目中侧边栏的各个页面:

文件名- AboutUs.js:

Javascript

import React from "react";
  
export const AboutUs = () => {
  return (
    
      

GeeksforGeeks About us

    
  ); };    export const OurAim = () => {   return (     
      

GeeksforGeeks Aim

    
  ); };    export const OurVision = () => {   return (     
      

GeeksforGeeks Vision

    
  ); };

文件名- ContactUs.js:

Javascript

import React from "react";
  
const Contact = () => {
  return (
    
      

GeeksforGeeks Contact us

    
  ); };    export default Contact;

文件名- Events.js:

Javascript

import React from "react";
  
export const Events = () => {
  return (
    
      

GeeksForGeeks Events

    
  ); };    export const EventsOne = () => {   return (     
      

GeeksforGeeks Event1

    
  ); };    export const EventsTwo = () => {   return (     
      

GeeksforGeeks Event2

    
  ); };

文件名-Services.js:

Javascript

import React from "react";
  
export const Services = () => {
  return (
    
      

GeeksforGeeks Services

    
  ); };    export const ServicesOne = () => {   return (     
      

GeeksforGeeks Service1

    
  ); };    export const ServicesTwo = () => {   return (     
      

GeeksforGeeks Service2

    
  ); };    export const ServicesThree = () => {   return (     
      

GeeksforGeeks Service3

    
  ); };

文件名- Support.js:

Javascript

import React from "react";
  
const Support = () => {
  return (
    
      

GeeksforGeeks Support us

    
  ); };    export default Support;

现在所有的页面和组件都准备好了,我们必须在我们的 App.js 文件中一一调用它们。

文件名 - App.js:

Javascript

import "./App.css";
import Sidebar from "./components/Sidebar";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { AboutUs, OurAim, OurVision } from "./pages/AboutUs";
import {
  Services,
  ServicesOne,
  ServicesTwo,
  ServicesThree,
} from "./pages/Services";
import { Events, EventsOne, EventsTwo } from "./pages/Events";
import Contact from "./pages/ContactUs";
import Support from "./pages/Support";
function App() {
  return (
    
      
      
        
        
        
        
        
        
        
        
        
        
        
        
      
    
  );
}
  
export default App;

Filename-App.css:根据你的修改CSS。

HTML

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
.home,
.services,
.reports,
.contact,
.events,
.support {
  display: flex;
  margin-left: 260px;
  font-size: 2rem;
}

运行项目:保存所有文件并使用以下命令启动服务器。

npm start

输出: