Vanilla JS重复请求API致功能仅生效一次的问题咨询与优化
Hey there! Let's fix both of your issues with a revised Vanilla JS implementation that's more efficient and robust:
Revised Code
// Cache the API data once globally let cachedDesigns = null; // Initialize the app by fetching data first function initApp() { const xhr = new XMLHttpRequest(); xhr.open("GET", 'http://www.pat-cooney.com/gd.json', true); xhr.onload = function() { if (this.status === 200) { cachedDesigns = JSON.parse(this.responseText); // Load initial content once data is ready loadDesigns(0); // Set up event listeners after content is rendered setupGalleryListeners(); } }; xhr.send(); } // Load content using cached data (no repeated API calls) function loadDesigns(index) { if (!cachedDesigns) return; // Exit if data isn't loaded yet let contentImages = `<img src="${cachedDesigns[index].images[0]}">`; let galleryNavOutput = ""; // Generate navigation images with data attributes instead of duplicate IDs for (let i = 0; i < 3; i++) { galleryNavOutput += `<img class="gallery-nav-item" data-index="${i}" src="${cachedDesigns[i].thumbnail}">`; } // Update the DOM with new content document.getElementById("inner").innerHTML = contentImages; document.getElementById("center").innerHTML = galleryNavOutput; } // Use event delegation to handle navigation clicks (works even when elements re-render) function setupGalleryListeners() { const galleryContainer = document.getElementById("center"); galleryContainer.addEventListener("click", function(e) { const target = e.target; // Check if we clicked on a navigation image if (target.classList.contains("gallery-nav-item")) { const index = parseInt(target.dataset.index); // Add small delay for UX feel setTimeout(() => loadDesigns(index), 300); } }); } // Start the app initApp();
1. Why & How We Fixed Repeated API Requests
Your original code called the API every time loadDesigns ran—this is inefficient, especially for a small static JSON file. Here's what changed:
- We moved the AJAX request to an
initAppfunction that runs once when the page loads - We store the fetched
designsdata in a globalcachedDesignsvariable - The
loadDesignsfunction now uses this cached data instead of making new requests every time you click a navigation item
This way, we only hit the API once, and reuse the data for all subsequent content switches.
2. Fixing the One-Time Click Issue (ID Conflicts & Event Binding)
The main problem here was duplicate IDs and lost event listeners:
- Duplicate IDs: Your original code generated elements with IDs like
one,two,threeevery timeloadDesignsran. HTML requires IDs to be unique on a page, so this caused DOM inconsistencies. We replaced these with a shared class (gallery-nav-item) and adata-indexattribute to track which item corresponds to which content. - Lost Event Listeners: You bound click events to the first set of navigation images, but when you re-rendered the navigation, the new elements didn't have those listeners. We fixed this with event delegation: we bind the click event to the parent container (
#center) instead of individual images. Since events bubble up, the parent can catch clicks on any child navigation image—even new ones that get rendered later.
We also simplified the timeout logic to avoid nested delays that could cause timing issues.
内容的提问来源于stack exchange,提问作者Pat Cooney
相关产品推荐
相关产品推荐

