如何为预测文本列表中匹配输入值的字符设置粗体样式?
解决方案
要实现列表项中匹配输入字符的高亮加粗,核心是将字符串拆分为匹配段与非匹配段,对匹配段应用样式后按原顺序重组。以下是修改后的完整代码及关键说明:
修改后的完整代码
HTML
<div class="search-container"> <input type="text" name="fruit" id="fruit" placeholder="Search fruit 🍎" /> <div class="suggestions"> <ul id="suggestions-list"></ul> </div> </div>
CSS
ul .has-suggestions { font-weight: bold; }
JavaScript
const fruit = ["Apple", "Banana", "Grape"]; let results = []; const input = document.getElementById('fruit'); const suggestionsList = document.getElementById('suggestions-list'); function search(str) { if (!str.trim()) return []; return fruit.filter(el => el.toLowerCase().includes(str.toLowerCase())); } function searchHandler(e) { suggestionsList.innerHTML = ""; showSuggestions(search(input.value), input.value); } function createHighlightedContent(text, matchStr) { const fragment = document.createDocumentFragment(); if (!matchStr.trim()) { fragment.appendChild(document.createTextNode(text)); return fragment; } const lowerMatch = matchStr.toLowerCase(); let currentPos = 0; let matchIndex = text.toLowerCase().indexOf(lowerMatch, currentPos); while (matchIndex !== -1) { if (matchIndex > currentPos) { fragment.appendChild(document.createTextNode(text.slice(currentPos, matchIndex))); } const highlightSpan = document.createElement('span'); highlightSpan.className = 'has-suggestions'; highlightSpan.textContent = text.slice(matchIndex, matchIndex + lowerMatch.length); fragment.appendChild(highlightSpan); currentPos = matchIndex + lowerMatch.length; matchIndex = text.toLowerCase().indexOf(lowerMatch, currentPos); } if (currentPos < text.length) { fragment.appendChild(document.createTextNode(text.slice(currentPos))); } return fragment; } function showSuggestions(results, inputVal) { for (const el of results) { const li = document.createElement('li'); li.appendChild(createHighlightedContent(el, inputVal)); suggestionsList.appendChild(li); } } input.addEventListener('input', searchHandler);
关键说明
- 高亮逻辑:
createHighlightedContent函数通过循环查找匹配位置,将非匹配文本以普通文本节点添加,匹配文本用带has-suggestions类的<span>包裹,确保原字符顺序不变且大小写保留。 - DOM性能:使用
DocumentFragment拼接节点,减少DOM操作次数,提升性能。 - 安全考量:避免直接使用
innerHTML插入内容,防止潜在XSS风险(若后续扩展用户输入内容时更安全)。 - 空输入处理:当输入为空时返回空数组,可根据需求调整为返回所有水果列表。
内容的提问来源于stack exchange,提问作者Kwok
相关产品推荐
相关产品推荐

