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 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);
마지막으로 이스터 에그를 남겨주세요. 위의 방법에도 작은 버그가 있으니 관심 있으신 분들은 찾아보시면 됩니다.
위 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.