You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按钮点击样式切换报错:Cannot read properties of undefined (reading 'className')

问题描述

页面右侧设有多个功能按钮,需要通过JavaScript实现点击切换激活样式:

  • 页面加载完成后,Home按钮通过active-btn类设置背景色为绿色
  • 首次点击其他按钮时,Home按钮背景色变为灰黑色,被点击按钮保持灰黑色,控制台无报错
  • 再次点击其他按钮时,按钮背景色无法正常切换,控制台报错:app.js:12 Uncaught TypeError: Cannot read properties of undefined (reading 'className')

相关代码

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Portfolio</title>
    <link rel="stylesheet" href="file://C:\Users\emile\Desktop\Portfolio Website\styles\style.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap" rel="stylesheet">
</head>
<body class="main-content">
    <header class="section sec1 header active"></header>
    <main>
        <section class="section sec2 about"></section>
        <section class="section sec3 portfolio"></section>
        <section class="section sec4 blogs"></section>
        <section class="section sec5 contact"></section>
    </main>

    <div class="controls">
        <div class="control control-1 active-btn" data-id="header">
            <i class="fas fa-home"></i>
        </div>
        <div class="control control-2" data-id="about">
            <i class="fas fa-user"></i>
        </div>
        <div class="control control-3" data-id="portfolio">
            <i class="fas fa-briefcase"></i>
        </div>
        <div class="control control-4" data-id="blogs">
            <i class="fas fa-newspaper"></i>
        </div>
        <div class="control control-5" data-id="contact">
            <i class="fas fa-envelope-open"></i>
        </div>       
    </div>

    <script src="C:\Users\emile\Desktop\Portfolio Website\app.js"></script>
</body>
</html>

CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  list-style: none;
}

:root {
  --color-primary: #191d2b;
  --color-secondary: #27AE60;
  --color-white: #FFFFFF;
  --color-black: #000;
  --color-grey0: #f8f8f8;
  --color-grey-1: #dbe1e8;
  --color-grey-2: #b2becd;
  --color-grey-3: #6c7983;
  --color-grey-4: #454e56;
  --color-grey-5: #2a2e35;
  --color-grey-6: #12181b;
  --br-sm-2: 14px;
  --box-shadow-1: 0 3px 15px rgba(0, 0, 0, .3);
}

body {
  background-color: var(--color-primary);
  font-family: "Poppins", sans-serif;
  font-size: 1.1rem;
  color: var(--color-white);
  transition: all 0.4s ease-in-out;
}

a {
  display: inline-block;
  color: inherit;
  font-family: inherit;
  text-decoration: none;
}

header {
  height: 100vh;
  color: var(--color-white);
  overflow: hidden;
}

section {
  min-height: 100vh;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding: 3rem 18rem;
}

.section {
  transform: translateY(-100%) scale(0);
  transition: all 0.4s ease-in-out;
  background-color: var(--color-primary);
}

.sec1 {
  display: none;
  transform: translateY(0) scale(1);
}

.sec2 {
  display: none;
  transform: translateY(0) scale(1);
}

.sec3 {
  display: none;
  transform: translateY(0) scale(1);
}

.sec4 {
  display: none;
  transform: translateY(0) scale(1);
}

.sec5 {
  display: none;
  transform: translateY(0) scale(1);
}

.controls {
  position: fixed;
  z-index: 10;
  top: 50%;
  right: 3%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transform: translateY(-50%);
}
.controls .active-btn {
  background-color: var(--color-secondary) !important;
  transition: all 0.4s ease-in-out;
}
.controls .active-btn i {
  color: var(--color-white) !important;
}
.controls .control {
  padding: 1rem;
  cursor: pointer;
  background-color: var(--color-grey-4);
  width: 55px;
  height: 55px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0.7rem 0;
  box-shadow: var(--box-shadow-1);
}
.controls .control i {
  font-size: 1.2rem;
  color: var(--color-grey-2);
  pointer-events: none;
}/*# sourceMappingURL=style.css.map */

原JavaScript代码

const sections = document.querySelectorAll('.section');
const sectBtns = document.querySelectorAll('.controls');
const sectBtn = document.querySelectorAll('.control');
const allSection = document.querySelector('.main-content');


function PageTransitions() {
    // Button click active class
    for (let i = 0; i < sectBtn.length; i++) {
        sectBtn[i].addEventListener('click', function() {
            let currentBtn = document.querySelectorAll('.active-btn');
            currentBtn[0].className = currentBtn[0].className.replace('active-btn', '');
            this.className += 'active-btn';
        })
    }
}

PageTransitions();
错误原因
  1. 类名拼接无空格:this.className += 'active-btn' 没有添加空格,导致多次点击后类名变成control control-2active-btn这种错误格式,后续document.querySelectorAll('.active-btn')无法找到目标元素,currentBtn[0]变为undefined,触发类型错误。
  2. 直接操作className风险:使用replace('active-btn', '')移除类名,若类名顺序变化或出现重复,可能无法正确移除,同时会破坏元素原有类结构。
修复方案

使用DOM原生的classListAPI操作类名,它能安全地添加、移除类,避免手动拼接类名的错误:

const sectBtn = document.querySelectorAll('.control');

function PageTransitions() {
    // 遍历按钮绑定点击事件
    sectBtn.forEach(btn => {
        btn.addEventListener('click', function() {
            // 移除所有按钮的激活类
            document.querySelectorAll('.active-btn').forEach(activeBtn => {
                activeBtn.classList.remove('active-btn');
            });
            // 为当前点击按钮添加激活类
            this.classList.add('active-btn');
        });
    });
}

PageTransitions();

优化说明

  • 用classList.add()和classList.remove()替代直接修改className,避免类名拼接错误和结构破坏
  • 使用forEach遍历元素,比for循环更简洁易读
  • 遍历所有带active-btn的元素移除类,避免依赖currentBtn[0]可能不存在的情况

内容的提问来源于stack exchange,提问作者Emlf9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:01:11