JS模擬瀏覽器全域性搜尋功能實現

loveEternity發表於2019-09-10

需求

需要像瀏覽器的全域性搜尋一樣,搜尋指定模組的對應值,然後將匹配到的內容新增背景顏色等。

思路

  • 需要取到當前指定區域的所有內容
  • 然後在取到的內容中找到搜尋的內容加上對應的背景顏色
  • 最後在將修改後的內容渲染到頁面上

實現

  • 利用innerHTML取到對應模組的內容
  • 編寫對應的正規表示式來匹配搜尋的內容
  • 利用String.prototype.replace替換匹配到的內容
  • 最後在渲染到頁面上

程式碼實現:

let wrap = document.querySelector('.wrap');
let innerHTML = wrap.innerHTML;
let reg = new RegExp(query, 'g');
innerHTML = innerHTML.replace(reg, '<span style="color: #000; background-color: #e3e4e5">' + query + '</span>');
wrap.innerHTML = innerHTML;
複製程式碼

具體的實現搜尋實現就完成了,但是上面程式碼還有個缺陷,就是更換搜尋內容時,之前搜尋的內容還是具有選中的樣式,那麼接下來完善功能:

let preQuery = ''; // 上一次搜尋的內容
let wrapDom = ''; // 搜尋區域的dom元素
function searchFn(dom, query) {
    let wrap = wrapDom || document.querySelector(dom);
    let innerHTML = wrap.innerHTML;
    if (!preQuery) {
        let preReg = new RegExp('<span style="color: #000; background-color: #e3e4e5">' + preQuery + '</span>', 'g');
        innerHTML = innerHTML.replace(preReg, preQuery);
    }
    if (query) {
        let reg = new RegExp(query, 'g');
        innerHTML = innerHTML.replace(reg, '<span style="color: #000; background-color: #e3e4e5">' + query + '</span>');
    }
    wrap.innerHTML = innerHTML;
    preQuery = query;
}
複製程式碼

至此搜尋高亮的功能就已經實現了。

注意事項

  • 搜尋區域的dom元素中不能使用title屬性,因為當使用title屬性時也會把對應的title屬性內容替換,頁面渲染時就會產生問題,其實可以將匹配規則的正規表示式重寫,但是能力有限,不知道如何編寫排除title屬性的正規表示式

  • 如果使用Vue等框架編寫時,搜尋完之後vue相關的事件和屬性全都失效了,因為我們這樣是直接把dom給換了,這種情況下有兩種解決方法:

      1. 搜尋完成之後,再例項化一次vue
    function resetVm() {
        vm.destroy()
        vm = new Vue({...})
    }
    複製程式碼

    但是這樣會有個問題,重新例項化vue例項之後,搜尋內容就沒了

      1. 不使用vue,可以用jQuery去實現頁面,這樣就不會有事件失效的問題

相關文章