ฉันเพิ่งพบฟังก์ชันเช่นนี้เมื่อทำงานในโครงการ: การเน้นคำหลักในหน้าเว็บ
ฉันคิดว่ามันจะเป็นการดำเนินการง่ายๆ ที่สามารถทำได้ด้วยการแทนที่ innerHTML แต่ฉันพบปัญหามากมาย บทความนี้บันทึกปัญหาเหล่านี้และวิธีแก้ปัญหาที่สมบูรณ์แบบขั้นสุดท้าย หวังว่าจะเป็นประโยชน์กับเพื่อน ๆ ที่มีประสบการณ์แบบเดียวกัน หากคุณสนใจเฉพาะผลลัพธ์ ไม่ต้องสนใจกระบวนการและข้ามเพื่อดูผลลัพธ์~
แนวทางปฏิบัติทั่วไป: การเปลี่ยนเป็นประจำแนวคิด: หากคุณต้องการเน้นองค์ประกอบต่างๆ คุณต้องแยกคำหลักและรวมไว้ในแท็ก จากนั้นจึงปรับรูปแบบของแท็ก ใช้ InnerHTML หรือ outHTML แต่ไม่ใช่ InnerText หรือ OutText
const regex = RegExp ใหม่(คำหลัก,g)element.innerHTML = element.innerHTML.replace(regex,<b class=a>+คำหลัก+</b>)element.classList.add(ไฮไลต์)
อันตรายที่ซ่อนอยู่ของการทำเช่นนี้มีดังนี้:
()/div<div id=parent> <div class=test>ทดสอบ</div> </div>
องค์ประกอบโหนดหลักของคำหลักดำเนินการประมวลผลการย้อมสีพื้นหลังผ่านคลาส ซึ่งทำให้ DOM ดั้งเดิมเสียหายในระดับหนึ่ง และอาจส่งผลต่อการเปลี่ยนตำแหน่งขององค์ประกอบ (ในฐานะปลั๊กอิน เราหวังว่าจะเปลี่ยน DOM ดั้งเดิมให้น้อยที่สุด)
การเพิ่มประสิทธิภาพปกติประการที่หนึ่ง: ประมวลผลองค์ประกอบที่อยู่ภายในแท็กเท่านั้นvar formatKeyword = text.replace(/[-////^$*+?.()|[/]{}]/g, '//$&') // หลีกอักขระพิเศษที่มีอยู่ในคำหลัก ตัวอย่างเช่น /.var finder = new RegExp(>.*?++.*?<) // แยกข้อความที่อยู่ในแท็กเพื่อหลีกเลี่ยงการทำงานผิดพลาดของคลาส, id ฯลฯ element.innerHTML = element.innerHTML.replace(finder,function(matched){ returnmatched.replace(text,<br>+text+</br>)})//แทนที่คีย์เวิร์ดในข้อความที่แยกออกมาภายในแท็ก
วิธีนี้สามารถแก้ไขปัญหาส่วนใหญ่ได้ แต่ปัญหาที่ยังคงมีอยู่ก็คือ ตราบใดที่มีสัญลักษณ์ < ที่คล้ายกันในแอตทริบิวต์แท็ก กฎการจับคู่จะใช้งานไม่ได้ และชุดข้อมูลการแยกข้อมูลปกติจะไม่ถูกต้อง ดังนั้นอักขระพิเศษเหล่านี้จึงหลีกเลี่ยงไม่ได้
<div dataset=p>d>แทนที่</div>การเพิ่มประสิทธิภาพปกติ 2: ล้างแท็กที่อาจได้รับผลกระทบ
<div id=keyword>คำหลัก</div> =》แทนที่แท็กปิดด้วยตัวแปร [replaced1]keyword[replaced2]//The id=keyword ในแท็กปิดจะไม่ได้รับการประมวลผล=》[replaced1]<b>คำหลัก </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 และไม่สามารถควบคุมสไตล์ได้อย่างอิสระ โหนดข้อความไม่สามารถแปลงเป็นโหนดธรรมดาได้ ซึ่งเป็นสิ่งที่น่าวิตกที่สุดเช่นกัน
ในที่สุด~ มาถึงจุดสำคัญของบทความนี้ เนื่องจากฟังก์ชันนี้ ฉันจึงได้ติดต่อกับโหนดข้อความอย่างจริงจังเป็นครั้งแรก จากที่นี่ ฉันค้นพบข้อความ และใช้วิธีการตัดโหนดข้อความและแทนที่โหนดเหล่านั้นเพื่อให้เกิดการเน้นสี
ซอร์สโค้ดและไฮไลท์การคืนค่า ดูซอร์สโค้ด
const reg = new RegExp(keyword.replace(/[-////^$*+?.()|[/]{}]/g, '//$&'))highlight = function (node,reg ){ if (node.nodeType == 3) { //ประมวลผลโหนดข้อความเท่านั้น const match = node.data.match(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);//เน้น สร้างโหนดสำเร็จแล้ว 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!