11ty站点内置搜索功能提交时跳转外部站点问题排查及优化方案咨询
解决11ty站点搜索表单提交仍跳转外部站点的问题
Hey there! Let's figure out why your search form is still jumping to DuckDuckGo even with preventDefault() in place.
问题根源
Looking at your code, the core issue is missing the id attribute on your search input:
- Your JavaScript tries to select the input with
document.querySelector('#search-input'), but your HTML input only has the classsearch-inputand no matchingid. - This makes
inputevaluate tonull, triggering the early return in this check:if (!form || !input || !resultList || !searchIndex) return; - Since the submit event listener never gets bound,
preventDefault()never runs, and the form uses its default behavior to submit to theactionURL (DuckDuckGo).
修正方案
Here's how to fix it, plus some optional improvements for better readability and functionality:
1. 修正HTML表单
Add the missing id to the input, and remove the action/method attributes (since we're handling the search client-side, we don't need the default form submission behavior):
<section id="hero"> <div class="container"> <div class="hero-buttons"> <h1 class="blog-header">11ty Search Demo</h1> <form id="form-search"> <!-- 添加id="search-input",并增加type="search"获得原生搜索体验 --> <input class="search-input" placeholder="Search here..." id="search-input" type="search" /> <button class="submit-search">Search</button> </form> <div id="search-results"></div> </div> </div> </section> <section id="blog"> <div class="container"> {%- for post in collections.post | reverse -%} {% include 'recent-snippet.njk' %} {%- endfor -%} </div> </section>
2. 优化JavaScript代码
Replace the messy HTML string concatenation with template literals for readability, and add a small improvement to handle empty input:
(function (window, document, undefined) { 'use strict'; let form = document.querySelector('#form-search'); let input = document.querySelector('#search-input'); let resultList = document.querySelector('#search-results'); /** * Create the HTML for each result * @param {Object} article The article * @param {Number} id The result index * @return {String} The markup */ let createHTML = function (article, id) { return ` <div id="search-result-${id}" class="search-result-item"> <a href="${article.url}"> <aside class="result-date">${article.date}</aside> <h2 class="result-title">${article.title}</h2> <p class="result-summary">${article.summary.slice(0, 150)}...</p> <span class="result-url">${article.url}</span> </a> </div> `; }; /** * Create the markup when no results are found * @return {String} The markup */ let createNoResultsHTML = function () { return '<p class="no-results">Sorry, no matches were found.</p>'; }; /** * Create the markup for results * @param {Array} results The results to display * @return {String} The results HTML */ let createResultsHTML = function (results) { let html = `<p class="results-count">Found ${results.length} matching articles</p>`; html += results.map(function (article, index) { return createHTML(article, index); }).join(''); return html; }; /** * Search for matches * @param {String} query The term to search for */ let search = function (query) { // 处理空输入 if (!query.trim()) { resultList.innerHTML = '<p class="empty-query">Please enter a search term.</p>'; return; } let reg = new RegExp(query.trim(), 'gi'); let priority1 = []; let priority2 = []; searchIndex.forEach(function (article) { if (reg.test(article.title)) return priority1.push(article); if (reg.test(article.blogTitle)) priority2.push(article); }); let results = [].concat(priority1, priority2); resultList.innerHTML = results.length < 1 ? createNoResultsHTML() : createResultsHTML(results); }; /** * Handle submit events */ let submitHandler = function (event) { event.preventDefault(); search(input.value); }; // 增加日志提示方便调试 if (!form || !input || !resultList || !searchIndex) { console.warn('Missing required elements or searchIndex for search functionality'); return; } form.addEventListener('submit', submitHandler); // 可选:添加回车/输入即时搜索支持 input.addEventListener('input', function() { // 可以加防抖函数避免频繁触发搜索 search(this.value); }); })(window, document);
额外优化建议
- 添加防抖(Debounce): 对于输入即时搜索,添加防抖函数可以减少搜索触发次数,提升性能。比如:
function debounce(func, delay = 300) { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } // 使用方式: input.addEventListener('input', debounce(function() { search(this.value); })); - 样式美化: 给搜索结果添加CSS样式,提升用户体验。
内容的提问来源于stack exchange,提问作者Mohammed Asker
相关产品推荐
相关产品推荐

