使用原生JavaScript实现元素递增延迟添加类的动画效果求助
问题分析与解决方案:原生JS替代jQuery的逐个元素动画
嘿,我来帮你理清楚问题出在哪,以及怎么修复!
首先看你写的原生JS代码,有两个关键错误导致lineItem[i]返回undefined:
错误1:forEach的参数搞反啦
你写的lineItem.forEach(i => { ... })里,这个i其实是当前遍历到的元素对象,而不是你以为的索引序号!forEach的正确参数顺序是(当前元素, 索引, 整个数组),所以你把元素当成索引来用,自然lineItem[i]就找不到东西啦——总不能用一个元素对象当数组下标吧😅
错误2:setTimeout回调里重复声明了i参数
你在setTimeout(function(i){ ... })里又声明了一个i参数,但是setTimeout执行这个回调的时候根本没传任何参数进去,所以这个i就是undefined,这也会导致lineItem[i]变成lineItem[undefined],结果肯定是undefined。
修复后的代码(两种写法)
写法1:用forEach的正确姿势
直接在forEach里拿到元素和索引,不用再通过数组下标获取元素,更直观:
const lineItems = document.querySelectorAll('.item'); lineItems.forEach((item, index) => { setTimeout(() => { // 用classList.add比直接拼className更安全,不会覆盖原有类 item.classList.add('is-visible'); console.log(item); // 直接打印当前元素就行 }, 200 * index); // 和你原来的jQuery逻辑一致,逐个延迟200ms });
写法2:用for循环(新手更容易理解)
如果forEach的参数顺序容易搞混,用for循环也可以,注意要用let声明i(避免闭包陷阱):
const lineItems = document.querySelectorAll('.item'); for (let i = 0; i < lineItems.length; i++) { setTimeout(() => { lineItems[i].classList.add('is-visible'); console.log(lineItems[i]); }, 200 * i); }
额外小提示
- 操作元素类名优先用
classList.add()/remove()/toggle(),比直接拼接className更安全,能避免重复添加同一个类或者不小心覆盖原有类的问题。 - 如果用for循环的话,一定要用
let而不是var声明循环变量,因为var是函数级作用域,所有setTimeout回调会共享同一个i,最后执行的时候i已经变成数组长度了,就找不到元素了。
内容的提问来源于stack exchange,提问作者Kuma
相关产品推荐
相关产品推荐

