有這麼乙個功能:在網頁中高亮關鍵字。
本以為乙個 innerhtml replace 就能實現的簡單操作,卻遇到了許多的問題。本文就記錄這些問題和最終的完美解決辦法, 希望能對有同樣遭遇的小夥伴有所幫助。只對結果感興趣的,忽略過程,直接跳過看結果吧~
思路:要想高亮元素,那麼需要將關鍵字提取出來用標籤包裹,然後對標籤進行樣式調整。使用 innerhtml,或 outhtml, 而不能使用 innertext,outtext。
const regex = new regexp(keyword,"g")
element.innerhtml = element.innerhtml.replace(regex,"a">"+keyword+"")
element.classlist.add("highlight")
複製**
這樣做存在的隱患有如下:
"parent">
"test">test
複製**
正則優化一:僅處理位於標籤內的元素var formatkeyword = text.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') // 轉義處理keyword包含的特殊字元,如 /.
var finder = new regexp(">.*?"++".*?<") // 提取位於標籤內的文字,避免誤操作 class、id 等
element.innerhtml = element.innerhtml.replace(finder,function(matched))// 對提取的標籤內文字進行關鍵字替換
複製**
以能解決大多數問題,但依舊存在的問題是,只要標籤屬性存在類似 < 符號,將會打破匹配規則導致正則提取內容錯誤, html5 dataset 可以自定義任意內容,故這些特殊字元是無法避免的。
"p>d">替換
複製**
正則優化二:清除可能影響的標籤"keyword">keyword
=》將閉合標籤用變數替換
[replaced1]keyword[replaced2]//閉合標籤內 id="keyword" 不會被處理
=》[replaced1]keyword[replaced2]
=》將暫存變數 replaced 替換為原先標籤
"keyword">keyword
複製**
這種思路及原始碼從這裡來, 但存在問題是:
總之在經過了n多嘗試之後,通過正則都沒能有效的處理各種情況。然後換了個思路,不通過字串的方式,通過節點處理。element.childnodes 可以最有效的清理標籤內的干擾資訊。
"parent">
keyword 1
"child">
keyword 2
複製**
通過 parent.childnodes 得到所有子節點。child 節點可以通過 innertext.replce(keyword,result) 的方式替換得到想要的高亮效果,如下:keyword2
(遞迴處理:當child節點不含子節點時進行replace操作)。
但是 keyword 1 是屬於文字節點,只能修改文字內容,無法增加 html,更無法單獨控制其樣式。而文字節點也不能轉換為普通節點,這也是最苦惱的事情。
最後~,本文的重點來了,因為這個功能,讓我第一次認真接觸到了文字節點這個東西。從這裡發現了text,使用切割文字節點並替換的方式實現高亮。
原始碼以及還原高亮見原始碼
const reg = new regexp(keyword.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'))
highlight = function (node,reg)
} else
if (node.nodetype == 1 && node.dataset.highlight!="y"
) }
}複製**
最後,留個彩蛋,以上方法也是存在乙個小 bug 的,有興趣可以去發現一下。 lucene 關鍵字高亮
indexwriter writer new indexwriter indexpath,analyzer,true document doca new document string filetexta 因為火燒雲總是燃燒著消失在太陽衝下地平線的時刻,然後便是寧靜的自然的天籟,沒有誰會在這樣的時光...
關鍵字高亮變色
在搜尋介面需要關鍵字與搜尋出來的文字高亮顯示並且不區分字母大小寫 關鍵字高亮變色 param color 變化的色值 param text 文字 param keyword 文字中的關鍵字 return 結果spannablestring public static spannablestring ...
qml listview關鍵字高亮
研究了一天多,最終能實現的只有以下這種方案。view通過listmodel載入資料,但是 資料必須是經過整理的。才能實現關鍵字高亮。首先要把資料擷取成一段一段的,再根據比較函式,確定是否高亮。最近研究qml頭髮都白了。1 import qtquick 2.9 2 import qtquick.win...