나는 최근 프로젝트를 진행하면서 웹페이지에서 키워드를 강조하는 것과 같은 기능을 접했습니다.
innerHTML 교체만으로 가능한 간단한 작업이라고 생각했는데, 많은 문제에 부딪혔습니다. 이 글은 같은 경험을 가진 친구들에게 도움이 되기를 바라면서 이러한 문제들과 최종적인 완벽한 해결책을 기록합니다. 결과에만 관심이 있으신 분은 과정을 무시하고 건너뛰어 결과를 확인하세요~
일반적인 관행: 정기적인 교체아이디어: 요소를 강조하려면 키워드를 추출하여 태그로 묶은 다음 태그 스타일을 조정해야 합니다. 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 match.replace(text,<br>+text+</br>)})//태그 내에서 추출된 텍스트의 키워드를 바꿉니다.
이렇게 하면 대부분의 문제를 해결할 수 있지만 여전히 존재하는 문제는 태그 속성에 유사한 < 기호가 있는 한 일치 규칙이 깨지고 일반 추출 콘텐츠가 잘못된 콘텐츠를 맞춤설정할 수 있다는 것입니다. 그래서 이러한 특수 문자는 피할 수 없습니다.
<div 데이터세트=p>d>바꾸기</div>일반 최적화 2: 영향을 받을 수 있는 태그 지우기
<div id=keyword>keyword</div> =》닫는 태그를 변수 [replaced1]keyword[replaced2]//닫는 태그의 id=keyword는 처리되지 않습니다=》[replaced1]<b>keyword </b >[replaced2] =》임시 변수를 원래 태그 <div id=keyword><b>keyword</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을 추가할 수 없으며 스타일을 독립적으로 제어할 수 없습니다. 텍스트 노드를 일반 노드로 변환할 수 없다는 점이 가장 괴로운 일이기도 합니다.
드디어~ 이 글의 핵심은 바로 이 기능 때문에 처음으로 텍스트 노드를 본격적으로 접하게 된 것입니다. 여기에서 텍스트를 발견하고 텍스트 노드를 잘라내고 교체하여 강조 표시하는 방법을 사용했습니다.
소스 코드 및 복원 하이라이트 소스 코드 참조
const reg = new RegExp(keyword.replace(/[-////^$*+?.()|[/]{}]/g, '//$&'))highlight = 함수(노드,reg ){ if (node.nodeType == 3) { //텍스트 노드만 처리 const match = node.data.match(new RegExp(reg)) if (match) { const 하이라이트El = document.createElement(b); 하이라이트El.dataset.highlight=y const wordNode = node.splitText(match.index) wordNode.splitText(match[0].length); // 첫 번째 키워드와 const 다음에 3개의 텍스트 노드로 자릅니다. wordNew = document.createTextNode(wordNode.data); 하이라이트El.appendChild(wordNew);//highlight 노드가 성공적으로 구축되었습니다 wordNode.parentNode.replaceChild(highlightEl, wordNode); // 텍스트 노드 교체} } else if (node.nodeType == 1 && node.dataset.highlight!=y ) { for (var i = 0 ; i < node.childNodes.length; i++) { 하이라이트(node.childNodes[i], reg);요약
위 내용은 편집자가 소개한 HTML 키워드 강조 표시에 대한 완벽한 솔루션입니다. 질문이 있는 경우 메시지를 남겨주시면 편집자가 제 시간에 답변해 드리겠습니다. 또한 VeVb 무술 웹사이트를 지원해 주신 모든 분들께 감사드립니다!