ES5实现Tab组件异常:点击任意Tab仅最后一个被选中
解决ES5 Tab组件循环绑定的选中问题
嘿,我完全懂你遇到的这个坑——这是ES5里var声明变量的经典作用域陷阱!咱们一步步来拆解问题和修复方案:
问题根源
你循环绑定点击事件时用了var tabLink = tabLinks[i];,但var是函数级作用域,所有的点击事件回调都会共享同一个tabLink变量。当循环结束后,这个变量会指向最后一个Tab链接,所以不管你点击哪个Tab,代码里操作的都是最后那个元素。
另外还有个小疏漏:你没移除其他Tab链接的is-active类,就算修复了作用域,之前选中的Tab也会一直保留高亮状态哦。
修复方案1:用立即执行函数(IIFE)隔离作用域
通过IIFE为每个循环迭代创建独立的作用域,把当前的Tab链接保存下来,让每个回调都能拿到自己对应的元素:
window.onload = function() { // Variables var tabLinks = document.getElementsByClassName('services-tab__link-item'); var tabContents = document.getElementsByClassName('services-tab__tab-item'); // Loop through the tab link for(var i = 0; i < tabLinks.length; i++) { // 用IIFE包裹,传入当前循环的tabLink (function(currentTab) { currentTab.addEventListener('click', function(e) { e.preventDefault(); // 先移除所有Tab链接的选中状态 for(var k = 0; k < tabLinks.length; k++) { tabLinks[k].classList.remove('is-active'); } // 获取当前Tab对应的内容ID var targetId = currentTab.hash.replace('#', ''); // 标记当前Tab为选中状态 currentTab.classList.add('is-active'); // 切换Tab内容显示 for(var j = 0; j < tabContents.length; j++) { var tabContent = tabContents[j]; tabContent.classList.remove('is-visible'); if(tabContent.id === targetId) { tabContent.classList.add('is-visible'); } } }); })(tabLinks[i]); // 把当前迭代的tabLink传入IIFE } }
修复方案2:用this获取当前触发元素(更简洁)
在点击事件的回调里,this会自动指向触发事件的DOM元素(也就是你点击的那个Tab链接),直接用this就能拿到正确的元素,不用依赖循环变量:
window.onload = function() { // Variables var tabLinks = document.getElementsByClassName('services-tab__link-item'); var tabContents = document.getElementsByClassName('services-tab__tab-item'); // Loop through the tab link for(var i = 0; i < tabLinks.length; i++) { tabLinks[i].addEventListener('click', function(e) { e.preventDefault(); var currentTab = this; // this指向当前被点击的Tab链接 // 移除所有Tab的选中状态 for(var k = 0; k < tabLinks.length; k++) { tabLinks[k].classList.remove('is-active'); } // 获取目标内容ID var targetId = currentTab.hash.replace('#', ''); // 标记当前Tab为选中 currentTab.classList.add('is-active'); // 切换内容显示 for(var j = 0; j < tabContents.length; j++) { var tabContent = tabContents[j]; tabContent.classList.remove('is-visible'); if(tabContent.id === targetId) { tabContent.classList.add('is-visible'); } } }); } }
额外优化点
- 直接用
tabContent.id代替tabContent.getAttribute('id'),写法更简洁高效 - 每次点击先清空所有Tab的选中状态,保证UI状态一致
内容的提问来源于stack exchange,提问作者Aurelian Spodarec
相关产品推荐
相关产品推荐

