Uncaught TypeError: addEventListener不是函数错误求助(VS Code无提示)
解决
allSections.addEventListener is not a function错误 控制台持续抛出错误:
Uncaught TypeError: allSections.addEventListener is not a function
at PageTransitions (app.js:16:17)
at app.js:33:1
VS Code编辑器中无错误提示,以下是相关代码:
JavaScript代码
const sections = document.querySelectorAll('.section'); const secBtns = document.querySelectorAll('.controls'); const secBtn = document.querySelectorAll('.control'); const allSections = document.querySelectorAll('.main-content'); function PageTransitions(){ for(let i = 0; i < secBtn.length; i++){ secBtn[i].addEventListener('click', function(){ let currentBtn = document.querySelectorAll('.active-btn'); currentBtn[0].className = currentBtn[0].className.replace('active-btn', '') this.className += ' active-btn'; }) } allSections.addEventListener('click', (e) =>{ const id = e.target.dataset.id; if(id) { secBtns.forEach((btn) => { btn.classList.remove('active') }) e.target.classList.add('active') sections.forEach((section)=>{ section.classList.remove('active') }) const element = document.getElementById(id); element.classList.add('active'); } }) } PageTransitions();
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="styles/styles.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:ital@1&family=Ubuntu:wght@300&display=swap" rel="stylesheet"> </head> <body class="main-content"> <header class="section sec1 header active" id="home"> </header> <main> <section class="section sec2 about" id="about"></section> <section class="section sec3 portfolio" id="portfolio"></section> <section class="section sec4 blogs" id="blogs"></section> <section class="section sec5 contacts" id="contact"></section> </main> <div class="controls"> <div class="control control-1 active-btn" data-id="home"> <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="far fa-newspaper"></i> </div> <div class="control control-5 " data-id="contact"> <i class="fas fa-envelope-open"></i> </div> </div> <script src="app.js"></script> </body> </html>
错误原因及解决方案
核心问题
document.querySelectorAll('.main-content')返回的是NodeList集合(即使页面中只有一个匹配元素),而addEventListener是单个DOM元素的方法,集合无法直接调用该方法,因此抛出类型错误。
从HTML代码可以看到,main-content是<body>标签的class,页面中只有一个,所以应该用document.querySelector('.main-content')获取单个元素,而不是querySelectorAll。
修正后的JavaScript代码
const sections = document.querySelectorAll('.section'); const secBtns = document.querySelectorAll('.controls'); const secBtn = document.querySelectorAll('.control'); // 替换querySelectorAll为querySelector,获取单个元素 const allSections = document.querySelector('.main-content'); function PageTransitions(){ // 用forEach替代for循环,更简洁 secBtn.forEach(btn => { btn.addEventListener('click', function(){ let currentBtn = document.querySelector('.active-btn'); // 用classList操作替代字符串替换,更可靠 currentBtn.classList.remove('active-btn'); this.classList.add('active-btn'); }) }); // 现在allSections是单个元素,可以正常绑定事件 allSections.addEventListener('click', (e) =>{ const id = e.target.dataset.id; if(id) { secBtns.forEach((btn) => { btn.classList.remove('active'); }); e.target.classList.add('active'); sections.forEach((section)=>{ section.classList.remove('active'); }); const element = document.getElementById(id); element.classList.add('active'); } }); } PageTransitions();
额外优化说明
- 用
querySelector替代querySelectorAll获取单个元素:当确定页面中只有一个匹配元素时,querySelector更高效,返回单个DOM元素,无需处理集合。 - 用
classList操作类名:直接修改className容易覆盖原有类名,classList.add()、classList.remove()是更安全的方式。 - 用
forEach替代for循环:遍历NodeList时,forEach代码更简洁易读,现代浏览器均支持。
内容的提问来源于stack exchange,提问作者codertrey
相关产品推荐
相关产品推荐

