在現代Web開發中,關鍵詞高亮是一個常見的需求。無論是在搜索引擎結果頁、文檔編輯器,還是在數據分析工具中,關鍵詞高亮都能幫助用戶快速定位重要信息。本文將詳細介紹如何使用純JavaScript實現一個高度可擴展的關鍵詞高亮功能。
關鍵詞高亮的基本原理是通過JavaScript操作DOM,將指定的關鍵詞用特定的HTML標簽包裹起來,并應用CSS樣式。例如,將關鍵詞“JavaScript”高亮顯示:
<p>This is a JavaScript example.</p>
高亮后:
<p>This is a <span class="highlight">JavaScript</span> example.</p>
首先,我們需要獲取需要高亮的文本節點??梢酝ㄟ^document.createTreeWalker
或NodeIterator
來遍歷DOM樹,找到所有的文本節點。
function getTextNodes(node) {
let textNodes = [];
let walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT, null, false);
while (walker.nextNode()) {
textNodes.push(walker.currentNode);
}
return textNodes;
}
接下來,我們需要將關鍵詞用<span>
標簽包裹起來??梢允褂?code>String.prototype.replace方法來實現。
function highlightKeyword(textNode, keyword) {
let text = textNode.nodeValue;
let regex = new RegExp(`(${keyword})`, 'gi');
let newText = text.replace(regex, '<span class="highlight">$1</span>');
if (newText !== text) {
let span = document.createElement('span');
span.innerHTML = newText;
textNode.parentNode.replaceChild(span, textNode);
}
}
最后,我們將上述方法應用到所有的文本節點上。
function applyHighlight(node, keyword) {
let textNodes = getTextNodes(node);
textNodes.forEach(textNode => highlightKeyword(textNode, keyword));
}
在實際應用中,文本結構可能非常復雜,包含多個嵌套的HTML標簽。為了確保高亮功能在這些情況下也能正常工作,我們需要對上述方法進行改進。
我們可以通過遞歸的方式處理所有的子節點,確保每個文本節點都能被正確高亮。
function applyHighlightRecursive(node, keyword) {
if (node.nodeType === Node.TEXT_NODE) {
highlightKeyword(node, keyword);
} else if (node.nodeType === Node.ELEMENT_NODE) {
Array.from(node.childNodes).forEach(child => applyHighlightRecursive(child, keyword));
}
}
如果文本中已經存在高亮標簽,我們需要確保不會重復高亮??梢酝ㄟ^檢查節點的父節點是否為高亮標簽來實現。
function highlightKeyword(textNode, keyword) {
let text = textNode.nodeValue;
let regex = new RegExp(`(${keyword})`, 'gi');
let newText = text.replace(regex, '<span class="highlight">$1</span>');
if (newText !== text && textNode.parentNode.nodeName !== 'SPAN') {
let span = document.createElement('span');
span.innerHTML = newText;
textNode.parentNode.replaceChild(span, textNode);
}
}
在實際應用中,我們可能需要同時高亮多個關鍵詞。為了實現這一點,我們可以對上述方法進行擴展。
我們可以將關鍵詞列表傳遞給高亮函數,并在每個文本節點上依次應用高亮。
function applyHighlightMulti(node, keywords) {
keywords.forEach(keyword => applyHighlightRecursive(node, keyword));
}
為了避免多個關鍵詞重復高亮同一段文本,我們需要在每次高亮后檢查文本節點是否已經被高亮。
function highlightKeywordMulti(textNode, keyword) {
let text = textNode.nodeValue;
let regex = new RegExp(`(${keyword})`, 'gi');
let newText = text.replace(regex, '<span class="highlight">$1</span>');
if (newText !== text && textNode.parentNode.nodeName !== 'SPAN') {
let span = document.createElement('span');
span.innerHTML = newText;
textNode.parentNode.replaceChild(span, textNode);
}
}
為了讓高亮效果更加靈活,我們可以通過CSS自定義高亮樣式。
我們可以在CSS中定義高亮樣式,并通過JavaScript動態添加或修改樣式。
.highlight {
background-color: yellow;
font-weight: bold;
}
我們可以通過JavaScript動態修改高亮樣式,例如根據關鍵詞的重要性調整顏色。
function applyHighlightStyle(style) {
let styleElement = document.createElement('style');
styleElement.innerHTML = `.highlight { ${style} }`;
document.head.appendChild(styleElement);
}
在處理大量文本或頻繁更新高亮時,性能可能成為一個問題。我們可以通過以下方法優化性能。
使用DocumentFragment
可以減少DOM操作次數,提高性能。
function applyHighlightOptimized(node, keyword) {
let fragment = document.createDocumentFragment();
let textNodes = getTextNodes(node);
textNodes.forEach(textNode => {
let span = document.createElement('span');
span.innerHTML = textNode.nodeValue.replace(new RegExp(`(${keyword})`, 'gi'), '<span class="highlight">$1</span>');
fragment.appendChild(span);
});
node.innerHTML = '';
node.appendChild(fragment);
}
對于非常大的文本,可以使用Web Workers在后臺線程中進行高亮處理,避免阻塞主線程。
let worker = new Worker('highlightWorker.js');
worker.onmessage = function(event) {
document.getElementById('content').innerHTML = event.data;
};
worker.postMessage({ text: document.getElementById('content').innerText, keywords: ['JavaScript', 'HTML'] });
除了基本的關鍵詞高亮,我們還可以擴展更多功能,例如:
可以高亮關鍵詞周圍的上下文,幫助用戶更好地理解匹配的內容。
function highlightContext(textNode, keyword, contextLength) {
let text = textNode.nodeValue;
let regex = new RegExp(`(.{0,${contextLength}}${keyword}.{0,${contextLength}})`, 'gi');
let newText = text.replace(regex, '<span class="highlight">$1</span>');
if (newText !== text) {
let span = document.createElement('span');
span.innerHTML = newText;
textNode.parentNode.replaceChild(span, textNode);
}
}
可以支持用戶輸入正則表達式進行高亮,提供更靈活的匹配方式。
function highlightRegex(textNode, regex) {
let text = textNode.nodeValue;
let newText = text.replace(regex, '<span class="highlight">$1</span>');
if (newText !== text) {
let span = document.createElement('span');
span.innerHTML = newText;
textNode.parentNode.replaceChild(span, textNode);
}
}
可以為高亮效果添加動畫,提升用戶體驗。
@keyframes highlightAnimation {
0% { background-color: yellow; }
50% { background-color: orange; }
100% { background-color: yellow; }
}
.highlight {
animation: highlightAnimation 1s infinite;
}
通過本文的介紹,我們詳細探討了如何使用純JavaScript實現一個高度可擴展的關鍵詞高亮功能。從基礎的高亮實現到處理復雜文本結構,再到性能優化和功能擴展,我們逐步構建了一個功能強大且靈活的關鍵詞高亮工具。希望本文能為你提供有價值的參考,幫助你在實際項目中實現類似的功能。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。