Gatsbyjs 中的自定义导航栏

Posted

技术标签:

【中文标题】Gatsbyjs 中的自定义导航栏【英文标题】:Custom Navbar in Gatsbyjs 【发布时间】:2021-12-13 03:25:07 【问题描述】:

我遇到了自定义导航栏的问题。我不会撒谎,我确实复制了它,但我想让它变得更好。我遇到的具体问题是在移动端。当我单击导航栏中的链接时,导航栏菜单不会消失。它停留在外面,页面加载到点击的链接。如何使用 useEffect 或 State 或 props 使导航栏滑出视图?

顺便说一句,tailwindCss 和 bootstrap 对我来说是不可能的,因为我想使用样式化组件并提高我的 css 技能。

感谢任何反馈。

编辑代码:

import React,  useState, useEffect, useRef  from "react";
import styled from "styled-components";
import  Link  from "gatsby";

const Navigation = styled.nav`
  display: flex;
  position: sticky;
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -ms-sticky;
  position: -o-sticky;
  background-color: var(--white);
  justify-content: space-between;
  text-transform: uppercase;
  border-bottom: 2px solid var(--light-green-shadow);
  width: 100%;
  margin: 0;
  top: 0;
  padding: 0.5rem 0;
  z-index: 2;
  align-items: center;
  box-sizing: border-box;
  transition: background ease-out 300ms;
  background: $( background ) => background ? `var(--light-green-tint)` : `var(--light-green)`;

  @media (max-width: 768px) 
    height: 5vh;
    position: sticky;
    top: 0;
    left: 0;
    right: 0;
    left: 0;
  
`

const Toggle = styled.div`
  display: none;
  height: 100%;
  cursor: pointer;
  padding: 0 10vw;

  @media (max-width: 768px) 
    display: flex;
  
`

const Navbox = styled.div`
  display: flex;
  height: 100%;
  justify-content: flex-end;
  align-items: center;
  box-sizing: border-box;
  
  ul 
        display: flex;
        align-items: center;
        width: 100;
        justify-content: end;
        gap: 2rem;
        padding: 0 1rem;
        flex-direction: row;
        li 
            list-style: none;
            transition: transform 500ms;
            :hover 
                transform: translateY(-10px);

            
            a 
                text-decoration: none;
                transition: color 300ms, transform 500ms;
                color: var(--white);
                :hover 
                    color: var(--light-grey);
                 
            
        
    

  @media (max-width: 768px) 
    flex-direction: column;
    position: fixed;
    width: 100%;
    justify-content: flex-start;
    padding-top: 10vh;
    background-color: var(--black);
    transition: all 0.3s ease-in;
    top: 6.5vh;
    right: $(open) => open ? "0" : "-100%";
    ul 
        flex-direction: column;
    
  
`

const LogoStyle = styled.div`
    margin-left: 2.5rem;
    a 
        text-decoration: none;
        white-space: nowrap; 
        font-size: 1.65rem;
        @media (min-width: 768px) 
            white-space: nowrap;
        
    
`;

const Hamburger = styled.div`
  background-color: #111;
  width: 30px;
  height: 3px;
  transition: all .3s linear;
  align-self: center;
  position: relative;
  transform: $(open) => open ? "rotate(-45deg)" : "inherit";

  ::before,
  ::after 
    width: 30px;
    height: 3px;
    background-color: #111;
    content: "";
    position: absolute;
    transition: all 0.3s linear;
  

  ::before 
    transform: $(open) => open ? "rotate(-90deg) translate(-10px, 0px)" : "rotate(0deg)";
    top: -10px;
  

  ::after 
    opacity: $(open) => open ? "0" : "1";
    transform: $(open) => open ? "rotate(90deg) " : "rotate(0deg)";
    top: 10px;
  
`
const Navbar = () => 
  const [navbarOpen, setNavbarOpen] = useState(false);

  const [background, setBackground] = useState(false);
    

  const changeBackground = () => 
      if (window.scrollY > 25) 
          setBackground(true);
       else 
          setBackground(false);
      
  

  const toggleNavbar = () => setNavbarOpen(open => !open);

  useEffect(() => 


      window.addEventListener('scroll', changeBackground);
      console.log(background);
      return () => 
          window.removeEventListener('scroll', changeBackground)
      
  ,[background]);


  return (
    <Navigation background=background>
       <LogoStyle> 
          <Link to="/">Performant Web Design</Link>
        </LogoStyle>
      <Toggle
        onClick= toggleNavbar()
      >
      <Hamburger open=navbarOpen />
      </Toggle>
      <Navbox open=navbarOpen>
        <ul>
            <li>
              <Link to='/services'>Services</Link>
            </li>
            <li>
                <Link to="/about">About</Link>
            </li>
            <li>
                <Link to="/contact">Contact</Link>
            </li>
        </ul>
      </Navbox>
    </Navigation>
  )


export default Navbar

【问题讨论】:

【参考方案1】:

默认情况下,当导航到另一个页面时,状态应该被重置。 Link 中的 onClick 不会产生任何效果,因为它不是组件接受的道具(它不是你的组件,而是 Gatsby 的)。尝试在那里调试,因为所有解决方案都会弄脏代码,因为它应该是默认行为。

与此同时,您可以做的是在您的&lt;li&gt; 中拦截该点击

const handleClick=(to)=>
   setNavbarOpen(false);
   navigate(to);


<li onClick=handleClick('/services')>
    <span>Services</span>
</li>

注意:这应该是一个临时解决方案,当您找到不稳定状态的原因时


按照你说的让它变得更好,你可以重构这个:

  const closeNav = () => 
    if (navbarOpen) 
      setNavbarOpen(false)
    
  

  const openNav = () => 
    if (!navbarOpen) 
      setNavbarOpen(true)
    
  

进入这个:

  const toggleNavbar = () => setNavbarOpen(!navbarOpen)

还有这个:

navbarOpen ? <Hamburger open /> : <Hamburger />

进入这个:

<Hamburger open=navbarOpen /> 

还有这个:

      navbarOpen ? (
        <Navbox>
            <ul>
                <li>
                    <Link to="/services" >Services</Link>
                </li> 
                <li>
                    <Link to="/about">About</Link>
                </li>
                <li>
                    <Link to="/contact">Contact</Link>
                </li>
            </ul>
            <IconComponent />
        </Navbox>
      ) : (
        <Navbox open>
            <ul>
                <li>
                    <Link to="/services" onClick=closeNav>Services</Link>
                </li>
                <li>
                    <Link to="/about">About</Link>
                </li>
                <li>
                    <Link to="/contact">Contact</Link>
                </li>
            </ul>
        </Navbox>
      )

就这样吧:

        <Navbox open=navbarOpen>
            <ul>
                <li>
                    <Link to="/services" onClick=closeNav>Services</Link>
                </li>
                <li>
                    <Link to="/about">About</Link>
                </li>
                <li>
                    <Link to="/contact">Contact</Link>
                </li>
            </ul>
        </Navbox>
      )

我将帮助您更好地调试(除其他外)。

【讨论】:

感谢您的帮助,是的,折射器确实有效,我稍微清理了样式。但是是的,在代码链接中遇到了与以前相同的问题。它适用于普通的 标签。导航方法确实改变了页面,并且快速加载的体验也在那里,但是菜单栏仍然存在问题。这有点奇怪,因为当 navbarOpen 状态为 false 时,组件应该会发生变化。我不知道该怎么做,我被困在这个问题上很长时间了。如果我也向您展示样式化的组件会有帮助吗? 当然。如果可以的话,尝试分享一个代码框,在那里提供帮助比猜测或查看部分代码要快 我可以给你一个我的 github 的链接吗?代码沙箱不工作。不知道是不是因为我有跨环境作为使用 ES6 模块而不是 commonJS 的依赖项 尝试尽可能多地分享信息,但请记住,这不是一个按需平台,克隆项目比在沙箱中实时定制项目要慢。它与常规的&lt;a&gt; 一起工作,因为它刷新了页面(在 React 的范围之外),因此您再次渲染所有内容,因此状态被重置。使用 Gatsby 的路由器,您只需刷新所需的部分(状态不同的部分),这就是为什么我建议使用 CodeSandbox 来检查所有设置的情况。您是否尝试过“肮脏的方法”? (只是为了检查它是否有效) 该解决方案的行为实际上是相同的,感谢您向我展示这种方式,因为我在导航功能上阅读了更多文档。现在我遇到了一个问题,因为 react 说我的导航栏组件正在无限循环中重新渲染。我在一个变量上使用了 useRef(true) 来查看它是否会从循环中逃脱,但不确定为什么现在会导致这种情况。大声笑我创建了一个全新的问题 OP 注释将包含来自导航栏组件的代码

以上是关于Gatsbyjs 中的自定义导航栏的主要内容,如果未能解决你的问题,请参考以下文章

iPad导航栏自定义高度

Flutter导航栏自定义效果

iOS NavigationBar 导航栏自定义

iOS 11导航栏自定义后退按钮问题

如何减少iOS导航栏自定义视图的左右间隙

无法执行单击导航栏自定义按钮