1.起因
今天在写一个页面的js的时候
想用var获取导航栏的元素
然后取成数组,然后再挨个添加函数
先移除现有的active类
然后再给被单机的那一项添加active类
var items=document.getElementsByClassName("nav-item");
for(var i=0;i<items.length;i++){
items[i].onclick=function () {
for(var p=0;p<items.length;p++){
items[p].classList.remove("active");
}
items[i].classList.add("active");
}
}
报错:
Uncaught TypeError: Cannot read property 'classList' of undefined
at HTMLLIElement.items.<computed>.onclick ((index):103)
items.<computed>.onclick @ (index):103
2.分析
出了错就要解决,那就开始debug,
a.我觉得可能是for循环的问题
那好,我去改,可是改来改去发现不对
后来想了想,现在这个项目引用了jquery
b.是不是这么写和jquery冲突呢?
后来发现压根也没关系,因为我注释了jquery的引用照样报错
c.是不是直接取这个变量也是获取不到呢,我就尝试再用一个中间变量去获取
还是报一样的错误
.
.
.
试了n种解决办法(以上省略N种无效解决办法)
N取余无穷的那种
和ylw讨论,他的方式是把
document.getElementsByClassName
换成
document.getElementById
然后用id去操控,这样确实可行
可是如果我的菜单栏目变多了
那就需要很多个id
然后挨个获取
然后挨个写函数,去除样式
不是很可行
最后,通过1个多小时的努力“走访”各大技术群
得到了两个正确的解法
解法1
let items=document.getElementsByClassName("nav-item");
for(var i=0;i<items.length;i++){
items[i].onclick=function () {
for(var p=0;p<items.length;p++){
items[p].classList.remove("active");
}
this.classList.add("active");
}
}
解法2
var items=document.getElementsByClassName("nav-item");
for(var i=0;i<items.length;i++){
items[i].onclick=function () {
for(var p=0;p<items.length;p++){
items[p].classList.remove("active");
}
this.classList.add("active");
}
}
3.总结反思
经过一系列的走访,才发现问题出在了
js的作用域上
如果照我第一种写法,那么最终获取的i始终是5
而数列为5的下标
也就是第六个元素根本不存在
所以这里就出来了作用域的问题
我们这里来看一个博客园的例子
for (var i = 0; i <10; i++) {
setTimeout(function() { // 同步注册回调函数到 异步的 宏任务队列。
console.log(i); // 执行此代码时,同步代码for循环已经执行完成
}, 0);
}
// 输出结果
10 共10个
// 这里面的知识点:JS的事件循环机制,setTimeout的机制等
===========================================
// i虽然在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // i 是循环体内局部作用域,不受外界影响。
}, 0);
}
// 输出结果:
0 1 2 3 4 5 6 7 8 9
let
非常适合用于 for
循环内部的块级作用域。JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域,用let声明的变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。
所以我们用了let和this就可实现我们的需求了
结果如下:
视屏
http://mpvideo.qpic.cn/0bf2dmacgaaasaahp6aeajqfag6demnqaiya.f10004.mp4?dis_k=888f40624951f5de2fe77ffcd19a9d11&dis_t=1650011069&vid=wxv_1699603327153389570&format_id=10004&support_redirect=0&mmversion=false