如何基于下拉选框选项更新用insertAdjacentHTML创建的HTML内容?
问题
页面加载时通过API拉取数据并生成HTML展示,我做了个下拉选择框用来给API返回的数组排序,现在排序后的数组能拿到正确结果,但新生成的HTML总是追加在旧内容后面,没法更新成排序后的新顺序。
原因分析
核心问题是你没在生成新内容前清空容器里的旧内容——每次调用getTours时,都用container.insertAdjacentHTML('beforeend', html)把新HTML往容器末尾加,旧内容一直留在那,自然就堆在一起了。另外还有几个小问题:
switch的default分支里写的out;是无效代码,不会起到保留原数组的作用- 每次选新排序都重新发API请求,完全没必要,第一次拿到数据后缓存起来,后续直接用缓存的数据排序就行
- 事件监听写复杂了,你已经用
querySelector拿到了下拉元素,不用再循环绑定
解决方案
1. 先清空旧内容
在遍历数组生成新HTML之前,先把容器的内容清空,最简单的就是用container.innerHTML = ''。
2. 缓存API数据
第一次请求到数据后存在变量里,后续排序直接操作缓存的数据,不用重复请求,速度更快。
3. 修复排序逻辑
把排序和渲染分开,单独写个排序函数,完善价格排序的逻辑(你原来的价格分支只有console.log,没实际排序),同时修复default分支的无效代码。
4. 简化事件绑定
直接给下拉元素绑定change事件就行,不用循环。
修改后的完整代码:
const container = document.querySelector('.container'); const sortSelect = document.querySelector('.sort'); let url = 'https://mocki.io/v1/11356aa2-6371-41d4-9d49-77a5e9e9924f'; let toursData = []; // 缓存API返回的原始数据 // 单独抽离渲染函数,负责把数据转成HTML并插入容器 function renderTours(data) { // 第一步:清空旧内容 container.innerHTML = ''; data.forEach((el,i) => { const cities = el.cities; const lastCity = cities.slice(-1) const dates = el.dates.map(d => d.start); let availableSpaces = el.dates.map(d => d.availability); const fromPrice = dates.length!==0 ? Math.min(...el.dates.map(item => item.eur)) : 0; const month = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEPT", "OCT", "NOV", "DEC"]; const getDate = function (date) { if (date!==undefined) { const d = new Date(date) const day = d.getDate(); const name = month[d.getMonth()] const year = d.getFullYear() const fullDate = `${day} ${name} ${year}`; return fullDate; } else { availableSpaces = ['No', 'No']; return 'SOLD OUT!' } } let image = el.images.filter(img => img.is_primary===true); image.length>0 && image[0].hasOwnProperty('url') && image[0].url!=='' ? image = image[0].url : image = "https://media.istockphoto.com/id/1357365823/vector/default-image-icon-vector-missing-picture-page-for-website-design-or-mobile-app-no-photo.jpg?s=612x612&w=0&k=20&c=PM_optEhHBTZkuJQLlCjLz-v3zzxp-1mpNQZsdjrbns="; const operatorName = el.operator_name; const html = `Here is my HTML text`; container.insertAdjacentHTML('beforeend', html); }); } // 首次加载获取数据并缓存 function getTours() { fetch(url) .then(res => res.json()) .then(data => { toursData = data; renderTours(toursData); // 渲染默认数据 }); } // 根据选择的选项排序数据并重新渲染 function sortTours(option) { // 复制原数组,避免修改缓存的原始数据 let sortedData = [...toursData]; switch(option) { case 'durasc': sortedData.sort((a,b) => a.length - b.length); break; case 'durdesc': sortedData.sort((a,b) => b.length - a.length); break; case 'prasc': // 按最低价格升序排序,无日期的排最后 sortedData.sort((a,b) => { const priceA = a.dates.length ? Math.min(...a.dates.map(item => item.eur)) : Infinity; const priceB = b.dates.length ? Math.min(...b.dates.map(item => item.eur)) : Infinity; return priceA - priceB; }); break; case 'prdesc': // 按最低价格降序排序,无日期的排最后 sortedData.sort((a,b) => { const priceA = a.dates.length ? Math.min(...a.dates.map(item => item.eur)) : -Infinity; const priceB = b.dates.length ? Math.min(...b.dates.map(item => item.eur)) : -Infinity; return priceB - priceA; }); break; default: // 默认返回原始数组 sortedData = toursData; break; } // 渲染排序后的数据 renderTours(sortedData); } // 绑定下拉选择事件 sortSelect.addEventListener('change', () => { sortTours(sortSelect.value); }); // 页面初始化 getTours();
内容的提问来源于stack exchange,提问作者Dragan
相关产品推荐
相关产品推荐

