点击切换游戏信息需多次点击的问题及jQuery搜索适配求助
问题:点击游戏名称切换详情需多次点击生效
我通过fetch获取游戏JSON数据,动态创建DOM结构实现点击游戏名称显示/隐藏详情,但现在需要多次点击才生效,同时还遇到搜索功能适配的问题,以下是相关代码和解决方案:
一、初始代码与问题分析
1. 动态创建DOM的JS代码
fetch("thething.json") .then(res => res.json()) .then(data =>{ games = data.map(game => { const newDiv = document.createElement("div"); newDiv.className = "game-info"; newDiv.innerHTML = ` <p onclick="toggler();">${game.Name}</p> <div class="info"> <img src="${game.Thumbnail}"> <p>${game.Description}</p> </div> `; document.body.appendChild(newDiv); return {name: game.Name, element: newDiv} }) })
2. JSON数据结构
[ { "Name": "gamename1", "Thumbnail": "https://imglocation", "Description": "This game is indeed a game" }, { "Name": "gamename2", "Thumbnail": "https://imglocation2", "Description": "This game2 is indeed a game2" } ]
3. 切换函数代码
function toggler(){ $('div.game-info').click(function(e){ $(this).children('.info').toggle(); }); }
问题根源
每次点击游戏名称的<p>标签时,都会执行toggler()函数,而这个函数又会给所有.game-info元素重复绑定点击事件。第一次点击只是完成事件绑定,第二次点击才会触发切换逻辑,所以需要多次点击才生效。另外直接绑定全局.game-info事件时,容易出现触发所有游戏详情的问题。
二、点击切换问题的解决方案
方案1:原生JS直接绑定单元素事件
修改动态创建DOM的逻辑,给每个游戏名称标签单独绑定点击事件,精准定位当前项的详情:
fetch("thething.json") .then(res => res.json()) .then(data =>{ games = data.map(game => { const newDiv = document.createElement("div"); newDiv.className = "game-info"; // 创建名称标签并绑定事件 const nameP = document.createElement("p"); nameP.textContent = game.Name; nameP.addEventListener('click', () => { infoDiv.classList.toggle('hidden'); }); // 创建详情区域 const infoDiv = document.createElement("div"); infoDiv.className = "info"; infoDiv.innerHTML = ` <img src="${game.Thumbnail}"> <p>${game.Description}</p> `; // 组装元素并插入页面 newDiv.appendChild(nameP); newDiv.appendChild(infoDiv); document.body.appendChild(newDiv); return {name: game.Name, element: newDiv} }) })
需要搭配CSS隐藏类:
.info.hidden { display: none; }
方案2:jQuery事件委托(更简洁)
移除动态DOM里的onclick属性,改用全局事件委托,避免重复绑定:
// 修改动态创建时的innerHTML部分,去掉onclick newDiv.innerHTML = ` <p class="toggle-name">${game.Name}</p> <div class="info"> <img src="${game.Thumbnail}"> <p>${game.Description}</p> </div> `; // 在全局范围内绑定事件委托(放在fetch外部) $(document).on('click', '.toggle-name', function(){ $(this).siblings('.info').toggle(); });
这种方式只会绑定一次全局事件,点击时直接定位到当前项的详情区域,无需多次点击。
三、搜索功能适配问题与解决方案
原原生JS搜索代码
searchInput.addEventListener("input", e=>{ const value = e.target.value.toLowerCase() games.forEach(game =>{ const isVisible = game.Name.toLowerCase().includes(value) game.element.classList.toggle("hide", !isVisible) }); })
该代码依赖map返回的{name: game.Name, element: newDiv}数组,通过数组项控制对应DOM的显示隐藏。
适配jQuery的解决方案
方案1:沿用原games数组逻辑
既保留之前的数组结构,又用jQuery实现搜索:
const searchInput = document.querySelector("[data-search]") $(searchInput).on("keyup", function(){ const value = $(this).val().toLowerCase(); games.forEach(game => { const isVisible = game.name.toLowerCase().includes(value); $(game.element).toggle(isVisible); }); });
方案2:直接通过DOM筛选(自行实现的版本)
const searchInput = document.querySelector("[data-search]") $(searchInput).on("keyup", function(){ let value = $(this).val().toLowerCase(); $(".game-info").filter(function(){ const gameName = $(this).find('.toggle-name').text().toLowerCase(); $(this).toggle(gameName.indexOf(value) > -1); }); });
内容的提问来源于stack exchange,提问作者Dimbot
相关产品推荐
相关产品推荐

