JavaScript过滤/映射后页面刷新:联系人列表重复添加问题求解
解决联系人列表点击按钮重复追加的问题
我基于随机用户API开发了联系人列表功能,页面包含输入框与按钮,点击按钮后要么加载新的10条用户数据并存入localStorage,要么根据输入框内容过滤已有数据。但当前遇到的问题是:每次点击按钮后,新数据都会追加到原有列表的后面,无法实现点击后刷新显示对应结果的效果。
问题原因
问题出在printData函数中:每次渲染数据时,都直接通过ul.appendChild(li)向列表容器添加新元素,但没有先清空容器内已有的内容,导致旧数据保留,新数据不断叠加。
解决方案
在渲染新数据之前,先清空列表容器的内容,推荐两种简洁高效的方式:
- 直接设置容器的
innerHTML为空字符串:ul.innerHTML = '' - 循环移除所有子元素:
while (ul.firstChild) ul.removeChild(ul.firstChild)
优先选择第一种方式,代码更简洁直观。
修改后的完整代码
JavaScript代码
async function fetchPeople() { const URL = 'https://randomuser.me/api/?results=10'; const res = await fetch(URL); let data = await res.json(); return data; } async function data(name) { let filteredData = []; if (name.length > 0) { let newdata = JSON.parse(localStorage.getItem('contacts')); filteredData = newdata.filter((contact) => { return contact.name.first.toLowerCase().includes(name); }); } else { let data = await fetchPeople(); localStorage.setItem('contacts', JSON.stringify(data.results)); filteredData = data.results; } return filteredData; } async function printData() { let ul = document.querySelector('#cards'); let name = document.querySelector('#contact').value.toLowerCase(); let filteredData = await data(name); // 关键:先清空容器内旧内容 ul.innerHTML = ''; filteredData.forEach((contact) => { let li = document.createElement('li'); li.innerHTML = ` <div class="card"> <img src="${contact.picture.large}" alt="${contact.name.first} ${contact.name.last}" class="card__image"> <h2 class="card__name">${contact.name.first} ${contact.name.last}</h2> <p class="card__email">${contact.email}</p> <p class="card__location">${contact.location.city}-${contact.location.state}</p> <button class="card__btn">${contact.location.country}</button> </div>`; ul.appendChild(li); }); }
HTML代码
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <section class="form"> <div class="search"> <h1>Contact List</h1> <div class='search__field'> <input type="text" name="contact" id="contact" placeholder="Nome do contato" class="search__name form-control"> <button type="button" onclick='printData()' class='btn btn-primary search__btn'>Search</button> </div> </div> </section> <section class="results"> <ul class="cards" id="cards"></ul> </section> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
额外优化说明
同时简化了data函数中多余的return语句:原else分支里的return filteredData被移除,因为函数末尾已经统一返回该变量,逻辑更简洁统一。
内容的提问来源于stack exchange,提问作者Kelson Batista
相关产品推荐
相关产品推荐

