Bei der Arbeit an einem Projekt bin ich kürzlich auf eine Funktion wie diese gestoßen: das Hervorheben von Schlüsselwörtern auf Webseiten.
Ich dachte, es wäre ein einfacher Vorgang, der mit innerHTML-Ersatz erreicht werden könnte, aber ich bin auf viele Probleme gestoßen. Dieser Artikel beschreibt diese Probleme und die endgültige perfekte Lösung und hofft, Freunden, die die gleiche Erfahrung gemacht haben, hilfreich zu sein. Wenn Sie nur an den Ergebnissen interessiert sind, ignorieren Sie den Vorgang und überspringen Sie den Vorgang, um die Ergebnisse anzuzeigen~
Gängige Praxis: regelmäßiger AustauschIdee: Wenn Sie Elemente hervorheben möchten, müssen Sie die Schlüsselwörter extrahieren und in Tags einschließen und dann den Stil der Tags anpassen. Verwenden Sie innerHTML oder outHTML, jedoch nicht innerText oder outText.
const regex = new RegExp(keyword,g)element.innerHTML = element.innerHTML.replace(regex,<b class=a>+keyword+</b>)element.classList.add(highlight)
Die versteckten Gefahren dabei sind folgende:
()/div<div id=parent> <div class=test>test</div> </div>
Das übergeordnete Knotenelement mit Schlüsselwort führt eine Hintergrundfärbungsverarbeitung durch die Klasse durch, was das ursprüngliche DOM bis zu einem gewissen Grad verschmutzt und sich auf die Neupositionierung des Elements auswirken kann. (Als Plug-In hoffen wir, das ursprüngliche DOM so wenig wie möglich zu ändern.)
Regelmäßige Optimierung eins: Nur Prozesselemente, die sich innerhalb von Tags befindenvar formatKeyword = text.replace(/[-////^$*+?.()|[/]{}]/g, '//$&') // Escape für die im Schlüsselwort enthaltenen Sonderzeichen, Zum Beispiel /.var finder = new RegExp(>.*?++.*?<) // Extrahieren Sie den im Tag befindlichen Text, um Fehlbedienungen von Klasse, ID usw. zu vermeiden. element.innerHTML = element.innerHTML.replace(finder,function(matched){ return matched.replace(text,<br>+text+</br>)})//Ersetzen Sie Schlüsselwörter im extrahierten Text innerhalb des Tags
Dies kann die meisten Probleme lösen, aber das Problem besteht immer noch darin, dass, solange das Tag-Attribut ein ähnliches <-Symbol enthält, die Übereinstimmungsregeln verletzt werden und der reguläre Extraktionsinhalt falsch ist. Der HTML5-Datensatz kann jeden Inhalt anpassen. Daher sind diese Sonderzeichen unvermeidlich.
<div dataset=p>d>Ersetzen</div>Regelmäßige Optimierung 2: Löschen Sie möglicherweise betroffene Tags
<div id=keyword>keyword</div> =》Ersetzen Sie das schließende Tag durch eine Variable [replaced1]keyword[replaced2]//Das id=keyword im schließenden Tag wird nicht verarbeitet=》[replaced1]<b>keyword </b >[replaced2] =》Ersetzen Sie die temporäre Variable durch das ursprüngliche Tag <div id=keyword><b>keyword</b></div>
Am wichtigsten ist, dass diese Methode das Tag nicht korrekt extrahieren kann, wenn der Tag-Wert das Symbol <> enthält.
Kurz gesagt, nach N vielen Versuchen wurden verschiedene Situationen durch die Regularisierung nicht effektiv gehandhabt. Dann habe ich es mir anders überlegt und es über Knoten statt über Strings verarbeitet. element.childNodes kann Interferenzinformationen in Tags am effektivsten bereinigen.
[Perfekte Lösung] Verarbeitung über DOM-Knoten<div id=parent> Schlüsselwort 1 <span id=child> Schlüsselwort 2 </span> </div>
Rufen Sie alle untergeordneten Knoten über parent.childNodes ab. Der untergeordnete Knoten kann wie folgt durch innerText.replce(keyword,result)
ersetzt werden, um den gewünschten Hervorhebungseffekt zu erzielen: <span id=child><b>keyword</b> 2</span>
(Rekursive Verarbeitung: wenn child Der Ersetzungsvorgang wird durchgeführt, wenn der Knoten keine untergeordneten Knoten enthält.
Schlüsselwort 1 ist jedoch ein Textknoten und kann nur den Textinhalt ändern, kein HTML hinzufügen und seinen Stil nicht unabhängig steuern. Textknoten können nicht in normale Knoten umgewandelt werden, was auch das Beunruhigendste ist.
Schließlich kommt hier der Schwerpunkt dieses Artikels. Aufgrund dieser Funktion bin ich zum ersten Mal ernsthaft mit Textknoten in Berührung gekommen. Von hier aus entdeckte ich Text und nutzte die Methode, Textknoten auszuschneiden und zu ersetzen, um eine Hervorhebung zu erreichen.
Quellcode und Wiederherstellungs-Highlights siehe Quellcode
const reg = new RegExp(keyword.replace(/[-////^$*+?.()|[/]{}]/g, '//$&'))highlight = function (node,reg ){ if (node.nodeType == 3) { //Nur Textknoten verarbeiten const match = node.data.match(new RegExp(reg)); if (match) { const highlightEl = document.createElement(b); highlightsEl.dataset.highlight=y const wordNode = node.splitText(match.index) wordNode.splitText(match[0].length); // Nach dem ersten Schlüsselwort und const in drei Textknoten schneiden wordNew = document.createTextNode(wordNode.data); highlightEl.appendChild(wordNew);//highlight Der Knoten wurde erfolgreich erstellt wordNode.parentNode.replaceChild(highlightEl, wordNode); // Ersetzen Sie den Textknoten} } else if (node.nodeType == 1 && node.dataset.highlight!=y ) { for (var i = 0 ; i < node.childNodes.length; i++) { highlight(node.childNodes[i], reg);Zusammenfassen
Das Obige ist die perfekte Lösung, um vom Herausgeber eingeführte Schlüsselwörter hervorzuheben. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Herausgeber wird Ihnen rechtzeitig antworten. Ich möchte mich auch bei allen für die Unterstützung der VeVb-Kampfsport-Website bedanken!