React实现滚动修改头部背景时addEventListener未定义报错如何解决
问题原因
- 错误从React中导入
window对象:window是浏览器宿主环境提供的全局变量,不属于React的导出内容,你代码中import React, { ..., window, ... } from "react"这行导入的window是undefined,自然调用addEventListener方法会触发类型错误。 window.scrollY大小写拼写错误:你代码里写的全小写window.scrolly是不存在的属性,返回肯定是undefined,正确的属性名是首字母大写的Y。- 组件命名不规范:React自定义组件必须首字母大写,你当前定义的小写
header不符合规范,可能引发渲染问题。 - 导航栏背景类名逻辑错误:你直接把布尔值
transparentHeader传给了className属性,布尔值不会生成有效类名,需要根据状态动态切换对应的CSS类。 img标签没有加alt属性:React中写img标签必须传入alt属性,否则会报语法警告。- 动态类名拼接错误:你写的
className={(classes.navlink, classes.headerSearch)}用了逗号运算符,最终只会返回最后一个类名,应该用模板字符串拼接的方式传入多个类名。
修复后的完整代码
import React, { Fragment, useState, useEffect } from "react"; import { Navbar, NavDropdown, Nav, Container } from "react-bootstrap"; import classes from "../../styles/header.module.css"; import { Icon } from "@iconify/react"; // 组件名首字母大写,符合React规范 export default function Header() { // 初始状态设为true,默认显示透明头部 const [transparentHeader, setHeader] = useState(true); const listenScrollEvent = () => { // 滚动距离超过50px时切换为非透明头部,可自行调整阈值 setHeader(window.scrollY <= 50); }; useEffect(() => { // 兼容SSR场景,先判断window是否存在 if (typeof window === 'undefined') return; window.addEventListener("scroll", listenScrollEvent); return () => window.removeEventListener("scroll", listenScrollEvent); }, []); return ( <Fragment> {/* 根据状态动态切换导航栏类名,需要在header.module.css中定义对应的类样式 */} <Navbar expand="md" fixed="top" className={transparentHeader ? classes.transparentHeader : classes.solidHeader} > <Container> <Navbar.Brand href="#home"> <img src="/header.png" alt="站点logo"></img> </Navbar.Brand> <Navbar.Toggle aria-controls="basic-navbar-nav" /> <Navbar.Collapse id="basic-navbar-nav"> <Nav className="me-auto"> <Nav.Link className={classes.navlink} href="/"> Home </Nav.Link> <Nav.Link href="#pricing" className={classes.navlink}> About </Nav.Link> <NavDropdown title="Services" id="collasible-nav-dropdown" className={classes.services} > <NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item> <NavDropdown.Item href="#action/3.2"> Another action </NavDropdown.Item> <NavDropdown.Item href="#action/3.3"> Something </NavDropdown.Item> <NavDropdown.Divider /> <NavDropdown.Item href="#action/3.4"> Separated link </NavDropdown.Item> </NavDropdown> <NavDropdown title="Pages" id="collasible-nav-dropdown" className={classes.services} > <NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item> <NavDropdown.Item href="#action/3.2"> Another action </NavDropdown.Item> <NavDropdown.Item href="#action/3.3"> Something </NavDropdown.Item> <NavDropdown.Divider /> <NavDropdown.Item href="#action/3.4"> Separated link </NavDropdown.Item> </NavDropdown> <NavDropdown title="Blogs" id="collasible-nav-dropdown" className={classes.services} > <Icon icon="bx:bx-chevron-down" /> <NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item> <NavDropdown.Item href="#action/3.2"> Another action </NavDropdown.Item> <NavDropdown.Item href="#action/3.3"> Something </NavDropdown.Item> <NavDropdown.Divider /> <NavDropdown.Item href="#action/3.4"> Separated link </NavDropdown.Item> </NavDropdown> <Nav.Link href="#pricing" className={classes.navlink}> Contact </Nav.Link> </Nav> <Nav> <Nav.Link href="#deets" className={`${classes.navlink} ${classes.headerSearch}`} > <Icon icon="bi:search" /> </Nav.Link> <Nav.Link href="#memes" className={`${classes.navlink} ${classes.SignIn}`} > Sign In </Nav.Link> </Nav> </Navbar.Collapse> </Container> </Navbar> </Fragment> ); }
补充说明
你需要在header.module.css中添加两个类对应的样式,示例如下:
.transparentHeader { background-color: transparent; transition: background-color 0.3s ease; } .solidHeader { background-color: #fff; /* 可替换为你需要的非透明背景色 */ transition: background-color 0.3s ease; }
内容的提问来源于stack exchange,提问作者Zia Yamin
相关产品推荐
相关产品推荐

