Недавно я столкнулся с такой функцией при работе над проектом: выделение ключевых слов на веб-страницах.
Я думал, что это будет простая операция, которую можно выполнить с помощью замены InternalHTML, но столкнулся со многими проблемами. В этой статье описаны эти проблемы и окончательное идеальное решение, в надежде быть полезным друзьям, имеющим такой же опыт. Если вас интересуют только результаты, игнорируйте процесс и пропустите его, чтобы увидеть результаты~
Обычная практика: регулярная заменаИдея: если вы хотите выделить элементы, вам нужно извлечь ключевые слова и обернуть их в теги, а затем настроить стиль тегов. Используйте 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>test</div> </div>
Элемент родительского узла ключевого слова выполняет обработку фонового окрашивания через класс, что в определенной степени загрязняет исходный DOM и может повлиять на изменение положения элемента. (В качестве плагина мы надеемся как можно меньше изменить исходный DOM)
Оптимизация обычная: обрабатывать только элементы, расположенные внутри тегов.var formatKeyword = text.replace(/[-////^$*+?.()|[/]{}]/g, '//$&') // Экранируем специальные символы, содержащиеся в ключевом слове, Например, /.var finder = new RegExp(>.*?++.*?<) // Извлекаем текст, расположенный в теге, чтобы избежать неправильной работы класса, идентификатора и т. д. 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>ключевое слово</div> =》Замените закрывающий тег переменной [replaced1]keyword[replaced2]//Ключевое слово id=в закрывающем теге не будет обработано=》[replaced1]<b>ключевое слово </b >[replaced2] =》Замените временную переменную, замененную исходным тегом <div id=keyword><b>keyword</b></div>
Самое главное, что этот метод не может правильно извлечь тег, если значение тега содержит символ <>.
Короче говоря, после N многих попыток различные ситуации не были эффективно решены с помощью регуляризации. Затем я передумал и обработал его через узлы, а не через строки. element.childNodes может наиболее эффективно очищать информацию о помехах в тегах.
[Идеальное решение] Обработка через узлы DOM<div id=parent> ключевое слово 1 <span id=child> ключевое слово 2 </span> </div>
Получите все дочерние узлы через родительский.childNodes. Дочерний узел можно заменить на innerText.replce(keyword,result)
чтобы получить желаемый эффект выделения следующим образом: <span id=child><b>keyword</b> 2</span>
(Рекурсивная обработка: когда дочерний узел Операция замены выполняется, когда узел не содержит дочерних узлов).
Однако ключевое слово 1 является текстовым узлом и может изменять только текстовое содержимое, не может добавлять HTML и не может самостоятельно управлять своим стилем. Текстовые узлы невозможно преобразовать в обычные, что тоже самое огорчающее.
Наконец~, вот и основная тема этой статьи. Благодаря этой функции я впервые серьезно столкнулся с текстовыми узлами. Отсюда я открыл для себя текст и использовал метод вырезания текстовых узлов и их замены для выделения.
Исходный код и основные моменты восстановления см. в исходном коде.
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); wordNew = document.createTextNode(wordNode.data); HighlightEl.appendChild(wordNew);//highlight Узел успешно построен wordNode.parentNode.replaceChild(highlightEl, wordNode // Заменяем текстовый узел} } else if (node.nodeType == 1 && node.dataset.highlight!=y ) { for (var i = 0) ; я < node.childNodes.length; я++) {highlight(node.childNodes[i], reg);Подвести итог
Вышеуказанное является идеальным решением для выделения ключевых слов в HTML, представленным редактором. Надеюсь, оно будет вам полезно. Если у вас есть какие-либо вопросы, оставьте мне сообщение, и редактор ответит вам вовремя. Я также хотел бы поблагодарить всех за поддержку сайта боевых искусств VeVb!