最近、プロジェクトに取り組んでいるときに、Web ページ内のキーワードを強調表示する次のような機能に遭遇しました。
innerHTML replace で実現できる簡単な操作だと思っていましたが、多くの問題が発生しました。この記事では、同じ経験を持つ友人の役に立つことを願って、これらの問題と最終的な完璧な解決策を記録します。結果のみに興味がある場合は、プロセスを無視してスキップして結果を確認してください~
一般的な方法: 定期的な交換アイデア: 要素を強調表示したい場合は、キーワードを抽出してタグで囲み、タグのスタイルを調整する必要があります。 innerHTML または outHTML を使用しますが、innerText または outText は使用しません。
const regex = new RegExp(keyword,g)element.innerHTML = element.innerHTML.replace(regex,<b class=a>+keyword+</b>)element.classList.add(highlight)
これを行うと次のような隠れた危険が潜んでいます。
()/div<div id=parent> <div class=test>テスト</div> </div>
キーワードの親ノード要素は、クラスを通じて背景染色処理を実行します。これにより、元の DOM がある程度汚染され、要素の再配置に影響を与える可能性があります。 (プラグインとして、元の DOM の変更をできるだけ少なくしたいと考えています)
通常の最適化 1: タグ内にある要素のみを処理しますvar formatKeyword = text.replace(/[-////^$*+?.()|[/]{}]/g, '//$&') // キーワードに含まれる特殊文字をエスケープします。例: /.var finder = new RegExp(>.*?++.*?<) // クラス、ID などの誤操作を避けるために、タグ内にあるテキストを抽出します。 element.innerHTML = element.innerHTML.replace(finder,function(matched){ return matched.replace(text,<br>+text+</br>)})//タグ内の抽出されたテキストのキーワードを置換します
これでほとんどの問題は解決できますが、依然として存在する問題は、タグ属性に同様の < 記号が存在する限り、一致ルールが破られ、通常の HTML5 データセットがあらゆるコンテンツをカスタマイズできるということです。したがって、これらの特殊文字は避けられません。
<div dataset=p>d>置換</div>定期的な最適化 2: 影響を受ける可能性のあるタグを削除する
<div id=keyword>keyword</div> =》終了タグを変数に置き換えます [replaced1]keyword[replaced2]//終了タグ内の id=keyword は処理されません=》[replaced1]<b>keyword </b >[replaced2] =》一時変数を元のタグ <div id=keyword><b>キーワード</b></div> に置き換えます。
最も重要なのは、タグ値に <> 記号が含まれている場合、このメソッドはタグを正しく抽出できないことです。
つまり、N 回試行しても、正則化によってさまざまな状況が効果的に処理されませんでした。そこで考えを変え、文字列ではなくノードを介して処理しました。 element.childNodes は、タグ内の干渉情報を最も効果的にクリーンアップできます。
【完璧な解決策】DOMノードを介した処理<div id=parent> キーワード 1 <span id=child> キーワード 2 </span> </div>
parent.childNodes を通じてすべての子ノードを取得します。次のように、子ノードをinnerText.replce(keyword,result)
に置き換えることで、目的の強調表示効果を得ることができます: <span id=child><b>keyword</b> 2</span>
(再帰処理: 子の場合)置換操作は、ノードに子ノードが含まれていない場合に実行されます)。
ただし、キーワード 1 はテキスト ノードであり、テキスト コンテンツの変更のみが可能で、HTML を追加できず、スタイルを個別に制御できません。テキスト ノードは通常のノードに変換できません。これが最も厄介なことでもあります。
ようやく~、ここからが今回の本題ですが、この機能のおかげで、初めてテキストノードに本格的に触れました。ここから Text を発見し、テキスト ノードを切り取って置き換える方法を使用してハイライトを実現しました。
ソースコードと復元のハイライトはソースコードを参照
const reg = new RegExp(keyword.replace(/[-////^$*+?.()|[/]{}]/g, '//$&'))highlight = function (node,reg ){ if (node.nodeType == 3) { //テキストノードのみを処理します const match =node.data.match(new RegExp(reg)) if (match) { const highlightEl = document.createElement(b); highlightEl.dataset.highlight=y const wordNode = node.splitText(match.index) wordNode.splitText(match[0].length); // 最初のキーワードと const の後で 3 つの Text ノードに分割します。 wordNew = document.createTextNode(wordNode.data);highlightEl.appendChild(wordNew);//ハイライトノードは正常に構築されました wordNode.parentNode.replaceChild(highlightEl, wordNode); // テキスト ノードを置換します} } else if (node.nodeType == 1 && node.dataset.highlight!=y ) { for (var i = 0) ; i < ノード.childNodes.length; i++) { ハイライト(ノード.childNodes[i], reg) } }要約する
上記は、エディターが紹介した HTML 内のキーワードを強調表示するための完璧なソリューションです。ご質問があれば、メッセージを残してください。編集者がすぐに返信します。また、VeVb武道サイトを応援してくださった皆様、誠にありがとうございました!