伪路由网站导航点击触发错误数组位置路由问题求助
问题根源与修复方案
这是典型的闭包作用域陷阱——循环里的事件回调共享了同一个r变量的引用,循环结束后r固定指向最后一个路由键(contact),所以所有导航项点击都会触发最后一个路由。下面是几种实用的修复方法:
方法1:用let声明循环变量(最简单)
把循环里的r用let声明,let会在每次迭代时创建独立的块级作用域,确保每个回调捕获的是当前迭代的r值:
function loadHTML(path){ console.log(path); fetch(path) .then(response=> response.text()) .then(text=> document.getElementById("root").innerHTML=text); } const routes={ home: "./core/pages/home.html", about: "./core/pages/about.html", contact: "./core/pages/contact.html" } function loadNav(){ var nav=document.getElementById("nav"); // 用let声明r,创建块级作用域 for(let r in routes){ var li=document.createElement("li"); li.innerHTML=r; li.onclick=()=>{ console.log(routes[r]); loadHTML(routes[r]); // 调用页面加载函数 } nav.append(li); } } loadNav();
方法2:用立即执行函数(IIFE)保存当前值
如果你的运行环境不支持ES6的let,可以用立即执行函数把当前r的值封装到独立作用域中:
function loadNav(){ var nav=document.getElementById("nav"); for(var r in routes){ var li=document.createElement("li"); li.innerHTML=r; // 用IIFE捕获当前迭代的r值 (function(currentRoute){ li.onclick=()=>{ console.log(routes[currentRoute]); loadHTML(routes[currentRoute]); } })(r); nav.append(li); } }
方法3:用Object.keys()结合forEach遍历
forEach的回调函数本身会创建独立作用域,从根源上避免共享变量的问题:
function loadNav(){ var nav=document.getElementById("nav"); Object.keys(routes).forEach(r=>{ var li=document.createElement("li"); li.innerHTML=r; li.onclick=()=>{ console.log(routes[r]); loadHTML(routes[r]); } nav.append(li); }); }
关于你尝试的addEventListener无效的说明
你之前用addEventListener没解决问题,本质还是没处理作用域陷阱——只要用上面任意一种方法固定住当前迭代的路由值,不管用onclick还是addEventListener都能正常工作,比如方法1里替换成:
li.addEventListener('click', ()=>{ loadHTML(routes[r]); });
内容的提问来源于stack exchange,提问作者Francesco Pauselli
相关产品推荐
相关产品推荐

