Gatsbyjs 中的自定义导航栏
Custom Navbar in Gatsbyjs
我在使用自定义导航栏时遇到问题。我不想撒谎,我确实复制了它,但我想让它变得更好。我遇到的具体问题是在移动端。当我在导航栏中单击 link 时,导航栏菜单不会消失。它保持在外面,页面加载到被点击的 link。如何使用 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
默认情况下,当导航到另一个页面时,状态应该被重置。 Link
中的 onClick
不会产生任何效果,因为它不是组件接受的 prop(它不是你的组件,它是 Gatsby 的)。尝试在那里调试,因为所有解决方案都会弄脏代码,因为它应该是默认行为。
与此同时,您可以做的是拦截您 <li>
中的点击
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>
)}
我会帮助你更好地调试(除其他外)。
我在使用自定义导航栏时遇到问题。我不想撒谎,我确实复制了它,但我想让它变得更好。我遇到的具体问题是在移动端。当我在导航栏中单击 link 时,导航栏菜单不会消失。它保持在外面,页面加载到被点击的 link。如何使用 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
默认情况下,当导航到另一个页面时,状态应该被重置。 Link
中的 onClick
不会产生任何效果,因为它不是组件接受的 prop(它不是你的组件,它是 Gatsby 的)。尝试在那里调试,因为所有解决方案都会弄脏代码,因为它应该是默认行为。
与此同时,您可以做的是拦截您 <li>
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>
)}
我会帮助你更好地调试(除其他外)。