Map循环中如何正确获取labels.name数组元素而非单个字符?
问题
数据源来自https://api.github.com/repos/vercel/next.js/issues,其中部分issue的labels字段是数组,每个label对象包含name属性。编写代码尝试渲染issue列表时,想分别显示labels数组的第1、2、3个元素,但使用${label.name[0]}时,只显示了该字符串的第一个字符。需要调整代码,在循环渲染issue的同时,分别展示labels数组的前三个元素。
原代码如下:
function fetchData() { fetch("https://api.github.com/repos/vercel/next.js/issues") .then((response) => { if (!response.ok) { throw Error("ERROR"); } return response.json(); }) .then((test) => { console.log(test); const html = test .map((user) => { return ` <ul id="myUL"> <div style="min-height: 50px;"> <div class="card card-body" style="width: 100%;"> <li><a href="#"> ${user.title} <button> ${user.labels.map((label, index) => { if (index === 0) { return ` ${label.name} `; } })} </button> <button> ${user.labels.map((label, index) => { if (index === 1) { return ` ${label.name} `; } })} </button> <button> ${user.labels.map((label, index) => { if (index === 2) { return ` ${label.name} `; } })} </button> </a></li> </div> </div> </ul> `; }) .join(""); console.log(html); document.querySelector("#app").insertAdjacentHTML("afterbegin", html); }) .catch((error) => { console.log(error); }); } fetchData(); function myFunction() { var input, filter, ul, li, a, i, txtValue; input = document.getElementById("myInput"); filter = input.value.toUpperCase(); ul = document.getElementById("myUL"); li = ul.getElementsByTagName("li"); for (i = 0; i < li.length; i++) { a = li[i].getElementsByTagName("a")[0]; txtValue = a.textContent || a.innerText; if (txtValue.toUpperCase().indexOf(filter) > -1) { li[i].style.display = ""; } else { li[i].style.display = "none"; } } }
解决方案
问题根源
你用label.name[0]出错,是因为label.name本身是字符串类型,不是数组——GitHub API返回的labels数组里,每个label对象的name是字符串,不是数组。对字符串取[0],会获取该字符串的第一个字符,这就是问题所在。
修正后的代码
直接通过索引访问labels数组的元素,同时优化代码结构,避免冗余循环,还修复了原代码中重复id的问题:
function fetchData() { fetch("https://api.github.com/repos/vercel/next.js/issues") .then((response) => { if (!response.ok) { throw Error("ERROR"); } return response.json(); }) .then((issues) => { const html = issues .map((issue) => { // 只取前3个标签,生成对应的按钮,标签不足时不生成空按钮 const labelButtons = issue.labels.slice(0, 3).map(label => ` <button>${label.name}</button> `).join(''); return ` <div style="min-height: 50px;"> <div class="card card-body" style="width: 100%;"> <ul class="issue-list"> <li> <a href="#">${issue.title}</a> ${labelButtons} </li> </ul> </div> </div> `; }) .join(""); document.querySelector("#app").insertAdjacentHTML("afterbegin", html); }) .catch((error) => { console.log(error); }); } fetchData(); function myFunction() { var input, filter, uls, li, a, i, txtValue; input = document.getElementById("myInput"); filter = input.value.toUpperCase(); // 原代码中每个ul用了相同的id,改成选择所有类名为issue-list的ul uls = document.querySelectorAll(".issue-list"); uls.forEach(ul => { li = ul.getElementsByTagName("li"); for (i = 0; i < li.length; i++) { a = li[i].getElementsByTagName("a")[0]; txtValue = a.textContent || a.innerText; if (txtValue.toUpperCase().indexOf(filter) > -1) { li[i].style.display = ""; } else { li[i].style.display = "none"; } } }); }
核心修改说明
- 去掉了原代码中每个按钮内重复的
labels.map循环,改用slice(0,3)截取前3个标签,一次性生成所有按钮,代码更简洁高效 - 修复了HTML中多个元素使用同一个
id="myUL"的错误(HTML规定id必须唯一),改用类名.issue-list统一选择 - 自动处理标签数量不足3个的情况,不会生成空按钮,避免页面出现无效元素
内容的提问来源于stack exchange,提问作者Univel
相关产品推荐
相关产品推荐

