如何将Autocomplete.js触发条件设置为结果列表滚动至底部?
Scroll-Triggered Loading with Autocomplete.js
Hey there! I totally get where you're coming from—Autocomplete.js docs can feel a bit dense when you're just starting out with JavaScript and this library. Let's walk through exactly how to set up that scroll-to-bottom trigger for loading more results, instead of the default input-based trigger.
Key Concepts to Understand
First, the default trigger behavior ties loading results to user input changes. To switch to scroll-based loading, we'll need to:
- Keep track of pagination state (current page number)
- Listen for scroll events on the results container
- Manually trigger the
srcfunction to load the next page when we hit the bottom - Append new results to the existing list instead of replacing them
Full Template Code
Here's a complete, working example you can adapt to your project:
// Initialize Autocomplete and keep a reference to the instance const autocomplete = new Autocomplete('#search-input', { minLength: 1, // Adjust based on when you want initial results to load // Customize how each result item is rendered (adjust to your needs) render: ({ element, item }) => { const resultItem = document.createElement('div'); resultItem.className = 'autocomplete-result-item'; resultItem.textContent = item.label; // Add click handler if needed resultItem.addEventListener('click', () => { document.getElementById('search-input').value = item.label; autocomplete.close(); }); return resultItem; }, // Our src function now accepts a custom params object for pagination src: async (query, params) => { const currentPage = params?.page || 1; // Replace this with your actual API endpoint const response = await fetch(`/api/search?query=${encodeURIComponent(query)}&page=${currentPage}`); const results = await response.json(); return results; // Expected format: array of objects with at least a "label" field } }); // Grab the results container (Autocomplete uses .autocomplete-results by default) const resultsContainer = document.querySelector('.autocomplete-results'); // Add scrollable styling to the container (critical for scroll events) resultsContainer.style.maxHeight = '300px'; resultsContainer.style.overflowY = 'auto'; // State variables to prevent duplicate requests and track pagination let isLoading = false; let currentPage = 1; let activeQuery = ''; // Scroll event listener to trigger load more resultsContainer.addEventListener('scroll', () => { // Check if we've scrolled to near the bottom (10px buffer to avoid edge cases) const isScrolledToBottom = resultsContainer.scrollTop + resultsContainer.clientHeight >= resultsContainer.scrollHeight - 10; if (isScrolledToBottom && !isLoading && activeQuery) { isLoading = true; currentPage++; // Load next page of results autocomplete.src(activeQuery, { page: currentPage }) .then(newResults => { if (newResults.length === 0) { // No more results—stop listening for scroll resultsContainer.removeEventListener('scroll', arguments.callee); // Optional: Add a "No more results" message const noMore = document.createElement('div'); noMore.textContent = 'No more results'; noMore.style.padding = '10px'; noMore.style.textAlign = 'center'; resultsContainer.appendChild(noMore); return; } // Append new results to the existing list autocomplete.results = [...autocomplete.results, ...newResults]; autocomplete.render(); isLoading = false; }) .catch(error => { console.error('Failed to load more results:', error); isLoading = false; }); } }); // Reset pagination when the user enters a new query autocomplete.on('input', (query) => { activeQuery = query; currentPage = 1; isLoading = false; // Re-enable scroll listener in case it was disabled earlier resultsContainer.addEventListener('scroll', arguments.callee); // Load first page of new results autocomplete.src(query, { page: 1 }) .then(initialResults => { autocomplete.results = initialResults; autocomplete.render(); }); });
Important Notes
- Scrollable Container: Make sure the
.autocomplete-resultscontainer has a fixedmaxHeightandoverflowY: auto—otherwise, there won't be a scrollbar to listen to. - Loading State: The
isLoadingflag prevents multiple concurrent requests when the user scrolls quickly. - Pagination Logic: Adjust the API endpoint and response handling to match your backend's pagination setup (some use
offsetinstead ofpage, for example). - UI Feedback: You can add a "Loading..." indicator by inserting an element into the results container while
isLoadingis true.
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

