如何用Next.Js实现响应式移动导航菜单?

5vf7fwbs  于 2022-10-01  发布在  其他
关注(0)|答案(1)|浏览(257)

bounty 4天后到期。这个问题的答案有资格获得+50的声誉奖励。nizz0k正在寻找来自可靠来源的答案

因此,我对如何在Next.js中实现响应式移动导航感到有点困惑。我的问题源于通过Java脚本和CSS处理菜单切换状态。

我的导航菜单遵循following tutorial from Log Rocket,但是教程中使用的方法是为Reaction编写的,没有说明Next.js如何应用CSS类名。简单的Reaction示例依赖于动态更新css,而大多数Next.js方法似乎都建议使用useState切换元素。这是有效的,但我失去了能够通过媒体查询和切换按钮控制导航的粒度。

我当前的实现检查一个布尔值useState以显示菜单,我希望它只应用于780px或更低的菜单。如果我从状态false开始,整个菜单不会呈现,包括切换它的按钮。如果我从true状态开始,则移动菜单将自动呈现为展开状态,这是我想要阻止的。这也导致当用户不在移动时(例如,如果菜单未切换,并且用户转到大屏幕尺寸),切换将完全移除菜单。

因此,问题变成了如何防止这种无意的行为?或者如何将移动菜单的默认状态设置为隐藏,同时保留单击以切换功能?

import { useState } from 'react'
import Link from 'next/Link'
import SiteLogo from '../components/CompLogo'
import navStyles from '../styles/Nav.module.css'

const Nav = () =>{

const [isNavExpanded, setIsNavExpanded] = useState(true)
return(
<div>
<nav className={navStyles.nav}>
<SiteLogo />
<button className={navStyles.hamburger} onClick={() => {
          setIsNavExpanded(!isNavExpanded);
          console.log("clicked");
          console.log(isNavExpanded);
        }}>
{/* icon from heroicons.com */}
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
  <path fillRule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clipRule="evenodd" />
</svg>

</button>
<div className={navStyles.navigation}>
    {isNavExpanded && 
    <ul className={navStyles.menu}>
        <li className={navStyles.links}>
            <Link href='/'>
                <a className={navStyles.anchors}>Home</a>
            </Link>
        </li>
        <li className={navStyles.links}>
            <Link href='/map'>
            <a className={navStyles.anchors}>Map Page</a>
                </Link>
        </li>
        <li className={navStyles.links}>
            <Link href='/about' >
            <a className={navStyles.anchors}>About</a>
                </Link>
        </li>
    </ul>
}
</div>
</nav>
</div>
    )
}

export default Nav

以下是我的css:

.nav {
background-color: white;
color: black;
width: 100%;
display: flex;
align-items: center;
position: relative;
padding: 0.5rem 0 rem;
}

.navigation {
    margin-left:auto;
}

.menu{
display: flex;
padding: 0;
}

.links{
list-style-type: none;
margin: 0 1rem;    
}

.links a {
text-decoration: none;
display: block;
width: 100%;
}

.hamburger{
border: 0;
height: 80px;
width: 80px;
padding: 0.5rem;
border-radius: 50%;
background-color: white;
cursor: pointer;
transition: background-color 0.2s ease-in-out;
position: absolute;
top: 50%;
right: 5px;
transform: translateY(-50%);
display: none;
}

@media screen and (max-width: 768px) {
    .hamburger {
        display: block;
      }
      .menu {
        position: absolute;
        top: 146px;
        left: 0;
        flex-direction: column;
        width: 100%;
        height: calc(100vh - 147px);
        background-color: white;
        border-top: 1px solid black;

      }

      .links {
        text-align: center;
        margin: 0;
      }
      .links a {
        color: black;
        width: 100%;
        padding: 1.5rem 0;
      }
      .links:hover {
        background-color: #eee;
      }
      .menu.expanded {
        display: block;
      }
}
pu3pd22g

pu3pd22g1#

不是按照你的代码,而是一个通用指南-

  • 重要信息-这仅供您理解,可能与您的代码不完全相同。

对于你来说,宽度是780px,你想要检查和设置移动菜单和桌面菜单。

步骤1-你必须检查屏幕的宽度,你可以用css媒体屏幕宽度来做这件事,但是然后你的组件将加载移动菜单和桌面菜单的所有数据,所以你可以写一个宽度改变的事件侦听器,并做一些事情,比如(假设宽度是一个状态)-

{width > 780px ? <DesktopMenu /> : <MobileMenu /> }

现在,您可以延迟加载这两个组件。

现在进入手机菜单部分-

**“打开菜单抽屉按钮”**默认情况下在手机屏幕上始终可见(切换按钮打开)。

  • 在OpenMenuDrawerButton上编写一个Click事件,以打开一个实际存放菜单布局的抽屉,并使用CSS来实现幻灯片效果或其他任何东西。
  • 再次使用状态来检查抽屉是否打开,让我们将此状态调用为visibleDrawer,然后使用OpenMenuDrawerButton{visibleDrawer:true}和抽屉本身中的关闭按钮来切换此状态。
{!visibleDrawer && < OpenMenuDrawerButton /> }

在您点击(打开抽屉)后隐藏opendrawer键。

  • 打开抽屉后,在抽屉上显示一个关闭按钮,该按钮将隐藏抽屉{visibleDrayer:False},并使OpenMenuDrawerButton出现在其位置。

如果你需要更多的解释,一定要写信。

相关问题