近項目做暈頭,一個接一個,其中遇到這樣的一個功能,在網頁中高亮關鍵字的實現方法,下面小編把實現代碼及解決方案分享給大家,感興趣的的朋友跟隨小編一起看看吧
最近做項目遇到這樣的一個功能:在網頁中高亮關鍵字。
本以為一個 innerHTML replace 就能實現的簡單操作,卻遇到了許多的問題。本文就記錄這些問題和最終的完美解決辦法, 希望能對有同樣遭遇的小伙伴有所幫助。只對結果感興趣的,忽略過程,直接跳過看結果吧~
常用做法:正則替換
思路:要想高亮元素,那么需要將關鍵字提取出來用標簽包裹,然后對標簽進行樣式調整。使用 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>
關鍵字父節點 element 通過 class 來進行背景染色處理,對原始DOM有一定程度污染,可能對 element 再次定位造成影響。(作為插件希望盡可能少改變原始DOM)
正則優化一:僅處理位于標簽內的元素
var formatKeyword = text.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') // 轉義處理keyword包含的特殊字符,如 /. var finder = new RegExp(">.*?"++".*?<") // 提取位于標簽內的文本,避免誤操作 class、id 等 element.innerHTML = element.innerHTML.replace(finder,function(matched){ return matched.replace(text,"<br>"+text+</br>) })// 對提取的標簽內文本進行關鍵字替換
以能解決大多數問題,但依舊存在的問題是,只要標簽屬性存在類似 < 符號,將會打破匹配規則導致正則提取內容錯誤, HTML5 dataset 可以自定義任意內容,故這些特殊字符是無法避免的。
<div dataset="p>d">替換</div>
正則優化二:清除可能影響的標簽
<div id="keyword">keyword</div> =》將閉合標簽用變量替換 [replaced1]keyword[replaced2]//閉合標簽內 id="keyword" 不會被處理 =》 [replaced1]<b>keyword</b>[replaced2] =》將暫存變量 replaced 替換為原先標簽 <div id="keyword"><b>keyword</b></div>
最重要的,當標簽值中包含 <> 符號時,此方法也不能正確的提取標簽
總之在經過了N多嘗試之后,通過正則都沒能有效的處理各種情況。然后換了個思路,不通過字符串的方式,通過節點處理。element.childNodes 可以最有效的清理標簽內的干擾信息。
[完美解決方案]通過 DOM 節點處理
<div id="parent"> keyword 1 <span id="child"> keyword 2 </span> </div>
通過 parent.childNodes 得到所有子節點。child 節點可以通過 innerText.replce(keyword,result) 的方式替換得到想要的高亮效果,如下: <span id="child"><b>keyword</b> 2</span> (遞歸處理:當child節點不含子節點時進行replace操作)。
但是 keyword 1 是屬于文本節點,只能修改文本內容,無法增加 HTML,更無法單獨控制其樣式。而文本節點也不能轉換為普通節點,這也是最苦惱的事情。
最后~,本文的重點來了,因為這個功能,讓我第一次認真接觸到了文本節點這個東西。從這里發現了Text,使用切割文本節點并替換的方式實現高亮。
源碼以及還原高亮見源碼
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); // 切割成前 關鍵詞 后三個Text 節點 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; i < node.childNodes.length; i++) { highlight(node.childNodes[i], reg); i++ } } }
總結
以上所述是小編給大家介紹的HTML高亮關鍵字的完美解決方案,希望對大家有所幫助,
學習從來不是一個人的事情,要有個相互監督的伙伴,想要學習或交流前端問題的小伙伴可以私信“學習”小明加群獲取2019web前端最新入門資料,一起學習,一起成長!
經常看到圖片有一道高亮光弧閃過很炫的效果,其原理很簡單可以用css3動畫就可以做出這樣的效果,用css3動畫控制position:absolute的left值,從左向右閃過,這個具體的請看以下代碼哈。效果截圖如下:
鼠標houver在盒子box上時動畫會停止,代碼如下:
<!Doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk2312"/>
<title>CSS3動畫實現高亮光弧效果</title>
<style type="text/css">
body{margin:0;padding:0;}
.box{width:1000px;margin:200px auto;height:500px;position:relative;text-align:center;}
.box:hover .rolled{
-webkit-animation-play-state:paused;
-moz-animation-play-state:paused;
-o-animation-play-state:paused;
-ms-animation-play-state:paused;
}
.rolled{
position:absolute;
top: 0;
width:80px;
height:500px;
background: -moz-linear-gradient(left,rgba(255,255,255,0)0,rgba(255,255,255,.2)50%,rgba(255,255,255,0)100%);
background: -webkit-gradient(linear,left top,right top,color-stop(0%,rgba(255,255,255,0)),color-stop(50%,rgba(255,255,255,.2)),color-stop(100%,rgba(255,255,255,0)));
background: -webkit-linear-gradient(left,rgba(255,255,255,0)0,rgba(255,255,255,.2)50%,rgba(255,255,255,0)100%);
background: -o-linear-gradient(left,rgba(255,255,255,0)0,rgba(255,255,255,.2)50%,rgba(255,255,255,0)100%);
-webkit-transform: skewX(-25deg);
-moz-transform: skewX(-25deg);
-webkit-animation:rolled 2.5s .2s ease both infinite;
-moz-animation:rolled 2.5s .2s ease both infinite;
-o-animation:rolled 2.5s .2s ease both infinite;
-ms-animation:rolled 2.5s .2s ease both infinite;
overflow: hidden;
}
@-webkit-keyframes rolled{
0%{left:-150px ;}
100%{left:920px;}
}
@-moz-keyframes rolled{
0%{left:-150px ;}
100%{left:920px;}
}
@-o-keyframes rolled{
0%{left:-150px ;}
100%{left:920px;}
}
@-ms-keyframes rolled{
0%{left:-150px ;}
100%{left:920px;}
}
@keyframes rolled{
0%{left:-150px ;}
100%{left:920px;}
}
</style>
</head>
<body>
<div class="box">
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806113158735.jpg">
<div class="rolled"></div>
</div>
</body>
</html>
查看效果演示:http://tangjiusheng.com/css3/page01.html
另外一種效果,鼠標houver時效果才出現(觸發),代碼如下:
<!Doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk2312"/>
<title>CSS3實現高亮光弧效果</title>
<style type="text/css">
body{
margin: 0;padding: 0;
}
.box{width:1000px;margin:200px auto;height:500px;position:relative;text-align:center;}
a.floor:before{
display: block;
height: 500px;
}
a.floor:hover:before{
-webkit-transition: left 1.5s;
-moz-transition: left 1.5s;
transition: left 1.5s;
left: 920px;
}
a.floor:before{
content: "";
position: absolute;
width: 80px;
height:500px;
top: 0;
left: -150px;
overflow: hidden;
background: -moz-linear-gradient(left,rgba(255,255,255,0)0,rgba(255,255,255,.2)50%,rgba(255,255,255,0)100%);
background: -webkit-gradient(linear,left top,right top,color-stop(0%,rgba(255,255,255,0)),color-stop(50%,rgba(255,255,255,.2)),color-stop(100%,rgba(255,255,255,0)));
background: -webkit-linear-gradient(left,rgba(255,255,255,0)0,rgba(255,255,255,.2)50%,rgba(255,255,255,0)100%);
background: -o-linear-gradient(left,rgba(255,255,255,0)0,rgba(255,255,255,.2)50%,rgba(255,255,255,0)100%);
-webkit-transform: skewX(-25deg);
-moz-transform: skewX(-25deg);
}
</style>
</head>
<body>
<div class="box">
<a class="floor" href="#"><img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806113158735.jpg"></a>
</div>
</body>
</html>
除注明外的文章,均為來源:湯久生博客,轉載請保留本文地址!
原文鏈接:http://tangjiusheng.com/css3/125.html
行代碼就能讓我的網站支持代碼高亮的工具庫,也支持在 Vue 中使用,強烈推薦給大家。
highlight.js 是一款使用 javascript 開發代碼高亮工具庫,能夠讓網頁上的代碼顯示接近我們使用的代碼編輯器的高亮樣式,從而看起來更舒服,增強閱讀體驗。
highlight.js 官網截圖
常來我網站的小伙伴都知道,我的文章有一個欄目是“前端”,主要推薦一下實用的前端開源項目或者組件庫,寫技術類文章免不了要貼代碼,我的網站基于 wordpress 搭建,此前我一直為找一款代碼高亮插件煩惱,但大部分 wordpress 的代碼高亮插件實在太臃腫,出來的樣式又不美觀。大多時候是截圖 VsCode 的代碼界面,甚至還用過 codepng 這個工具把代碼變成圖片貼在文章中,但這樣做是美觀了,但也存在2個問題:
最終還是找到了 highlight.js,完美解決了上面兩個問題,而且配置簡單,演示漂亮,定制化簡單。不禁感嘆:用純前端的方式解決,才能精準控制,實現想要的效果。
下面以我的網站為例,展示將 highlight.js 用在我們的項目上的方法。首先 highlight.js 支持 cdn 直接引入和 npm 安裝,我的網站基于 wordpress 開發,主題是自己寫的,最簡單的方式就是在文章詳情頁引入 highlight.js 和主題樣式。
雖然 highlight.js 支持幾百種開發語言,但為了將文件體積控制到最小,我們可以點擊“get version”按鈕進入下載頁,通過勾選我們需要的開發語言,來構建最輕量的庫。
下載解壓后得到的 highlight.min.js 就是我們需要引入的 js 文件,主題樣式都在 style 文件夾里,我選擇了一個比較喜歡的 monokai-sublime 主題,只需要一個 css 文件,然后初始化:
<link href="/js/monokai-sublime.min.css" rel="stylesheet" type="text/css">
<script src="/js/highlight.min.js"></script>
<script>
hljs.highlightAll();
</script>
就是這么簡單,highlight.js 會自動將文章中的 <pre><code></code></pre> 代碼進行識別語言并且高亮,一切就是這么簡單。為了讓代碼顯示更協調,我用幾行 css 控制了包裹層的圓角以及背景顏色、字體大小等,大功告成。
.post-content .wp-block-code {
background-color: #F6F8FF;
border-radius: 16px;
font-size: 16px;
padding: 22px 22px 22px 38px;
margin-top: 22px;
margin-bottom: 22px;
}
.post-content .wp-block-code {
line-height: 1.2;
font-size: 15px;
padding: 10px;
overflow-x: auto;
}
.post-content .wp-block-code code {
position: relative;
background-color: unset !important;
}
當然 highlight.js 也能在 vue 項目中使用,安裝:
npm install highlight.js
在 Vue 文件中使用 (通過 highlight.js for Vue ) :
<div id="app">
<!-- bind to a data property named `code` -->
<highlightjs autodetect :code="code" />
<!-- or literal code works as well -->
<highlightjs language='javascript' code="var x = 5;" />
</div>
需要注意的是,自動識別模式不能100%識別出代碼所屬的開發語言,識別錯誤會導致高亮樣式是別的語言的,這種情況下可以手動設置一個 class 來精準控制:
<pre><code class="language-javascript">...</code></pre>
官網提供了詳盡的使用文檔,有更多代碼高亮的控制,但不足的就是 highlight.js 沒有顯示行號的支持,需要通過再引入一個庫 (highlightjs-line-numbers.js) 或者自行實現。
highlight.js 是一款基于 BSD 許可證開源的 javascript 工具庫,任何個人和公司都可以免費下載用于自己的項目,包括商用項目。
關注我,持續分享高質量的免費開源、免費商用的資源。
↓↓點擊查看本次分享的網址以及代碼高亮效果
highlight.js - 讓網頁上的代碼高亮美化的免費開源工具庫|那些免費的磚
*請認真填寫需求信息,我們會在24小時內與您取得聯系。