前端實現類瀏覽器的 Ctrl+F 全局搜索功能(Vue2 + mark.js,用于Electron 、QT等沒有瀏覽器Ctrl+F全局搜索功能的殼子中)

💻 在 Electron 中實現類瀏覽器的 Ctrl+F 全局搜索功能(Vue2 + mark.js)

本文介紹如何在 Electron 應用中構建一個像 Chrome 一樣的 Ctrl+F 查找框,支持全局高亮、滾動定位、關鍵詞計數與上下跳轉。


在這里插入圖片描述

? 背景

在網頁瀏覽器中,Ctrl+F 是用戶非常熟悉的操作,用于快速搜索頁面內容。而 Electron 作為構建桌面應用的強大工具,默認沒有提供類似功能,除了使用electron的findInPage api,直接在渲染進程即頁面代碼中實現也是一種方案,mark.js開源庫可以簡單快速實現功能:

  • 關鍵詞高亮
  • 跳轉到目標項
  • 支持多次匹配
  • 上下導航、實時計數

📦 安裝 mark.js

npm install mark.js

mark.js 是一個輕量級的 JavaScript 高亮庫,用于在網頁上高亮關鍵詞,常用于搜索結果展示。

? 主要功能

在指定容器內高亮關鍵詞

支持排除特定元素(通過 exclude 選項)

??基本原理簡化說明

遍歷 DOM 節點:遞歸遍歷所有子節點(跳過排除節點)。

查找匹配:在文本節點中使用正則或字符串查找關鍵詞。

插入<mark>標簽:將關鍵詞部分包裹在<mark>元素中插入 DOM


🧩 功能組件結構

我們封裝了一個 SearchBox 組件,掛載到 App.vue 中,監聽全局 keydown 事件,只要按下 Ctrl+F,搜索框就會彈出。

💡 核心特性:

功能點實現說明
Ctrl+F 打開搜索框keydown 全局監聽
ESC 或點擊 X 關閉搜索框清除高亮并隱藏組件
實時搜索關鍵詞使用 mark.js 動態高亮
上下跳轉匹配項通過數組索引控制焦點
當前項橙色,其它項黃色樣式區分當前匹配項
平滑過渡動畫transition + CSS 動畫

🧩 組件代碼(SearchBox.vue)

🔎 mark.js 搜索

const instance = new Mark(document.body);
instance.mark(this.keyword, {separateWordSearch: false,exclude: ['.count_num'], // 可排除domdone: () => {const elements = document.querySelectorAll('mark');this.markedElements = Array.from(elements);this.total = this.markedElements.length;this.current = 0;}
});

🔁 上下跳轉高亮邏輯

highlightCurrent() {this.markedElements.forEach((el, i) => {el.style.backgroundColor = i + 1 === this.current ? 'orange' : 'yellow';el.style.color = i + 1 === this.current ? '#000' : '';});this.markedElements[this.current - 1]?.scrollIntoView({block: 'center',});
}

🎬 動畫過渡

.slide-fade-enter-active,
.slide-fade-leave-active {transition: all 0.3s ease;
}
.slide-fade-enter,
.slide-fade-leave-to {transform: translateY(-20px);opacity: 0;
}

📥 App.vue 中掛載組件

App.vue 引入:

<template><div id="app"><SearchBox /><router-view /></div>
</template><script>
import SearchBox from './components/SearchBox.vue';export default {components: { SearchBox },
};
</script>

? 效果預覽

  1. Ctrl+F 打開搜索框
  2. 輸入關鍵詞即時高亮
  3. 顯示總匹配數 + 當前索引
  4. 點擊上下箭頭跳轉目標
  5. X 關閉框并清除所有高亮

整體交互體驗幾乎還原瀏覽器的搜索能力


🔚 結語與完整代碼

通過 mark.js 和 Vue 的組合,我們就能在 Electron 中還原 Ctrl+F 搜索體驗。

可直接復制下方代碼在項目中使用。

<template><transition name="slide-fade"><divv-if="visible"class="search-box"><inputv-model="keyword"@input="onInput"placeholder="搜索..." /><span class="count"><span class="count_num">{{ current }}/{{ total }}</span></span><iclass="vxe-icon-arrow-up":class="{ disabled: total === 0 }"@click="prev"></i><iclass="vxe-icon-arrow-down":class="{ disabled: total === 0 }"@click="next"></i><iclass="vxe-icon-close"@click="close"></i></div></transition>
</template><script>
import Mark from 'mark.js';export default {data() {return {keyword: '',current: 0,total: 0,visible: false,markedElements: [],};},mounted() {document.addEventListener('keydown', this.onKeydown);},beforeDestroy() {document.removeEventListener('keydown', this.onKeydown);},methods: {onKeydown(e) {console.log(111, e);if ((e.ctrlKey || e.metaKey) && (e.key === 'f' || e.key === 'F')) {e.preventDefault();this.visible = true;this.$nextTick(() => this.$el.querySelector('input').focus());}},close() {this.visible = false;this.clearMarks();this.keyword = '';this.current = 0;this.total = 0;},onInput() {this.clearMarks();if (!this.keyword.trim()) {this.current = 0;this.total = 0;return;}const instance = new Mark(document.body);instance.mark(this.keyword, {separateWordSearch: false,exclude: ['.czp-link', '.count_num'],done: () => {const elements = document.querySelectorAll('mark');this.markedElements = Array.from(elements);this.total = this.markedElements.length;this.current = 0;},});},clearMarks() {const instance = new Mark(document.body);instance.unmark();this.markedElements = [];},highlightCurrent() {this.markedElements.forEach((el, i) => {el.style.backgroundColor = i + 1 === this.current ? 'orange' : 'yellow';el.style.color = i + 1 === this.current ? '#000' : '';});if (this.markedElements[this.current - 1]) {this.markedElements[this.current - 1].scrollIntoView({//   behavior: 'smooth',block: 'center',});}},next() {if (this.total === 0) return;this.current = this.current < this.total ? this.current + 1 : 1;this.highlightCurrent();},prev() {if (this.total === 0) return;this.current = this.current > 1 ? this.current - 1 : this.total;this.highlightCurrent();},},
};
</script><style lang="scss" scoped>
.search-box {position: fixed;top: 60px;right: 15px;background: #fff;border: 1px solid #ccc;box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);border-radius: 4px;padding: 6px 10px;display: flex;align-items: center;z-index: 9999;font-size: 14px;input {flex: 1;padding: 4px 8px;border: 1px solid #ddd;border-radius: 3px;outline: none;}.count {min-width: 40px;text-align: center;color: #555;margin-left: 10px;margin-right: 10px;}.vxe-icon-arrow-up {font-size: 14px;color: #535353;cursor: pointer;}.vxe-icon-arrow-down {font-size: 14px;color: #535353;margin-left: 15px;cursor: pointer;}.vxe-icon-close {font-size: 10px;font-weight: bold;color: #535353;margin-left: 15px;cursor: pointer;}.disabled {color: #a9a9aa;cursor: not-allowed;}
}.slide-fade-enter-active {transition: all 0.3s ease;
}
.slide-fade-leave-active {transition: all 0.3s ease;
}
.slide-fade-enter {transform: translateY(-20px);opacity: 0;
}
.slide-fade-leave-to {transform: translateY(-20px);opacity: 0;
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92707.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92707.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92707.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

詳解力扣高頻 SQL 50 題-1757.可回收且低脂的產品【入門】

傳送門&#xff1a;可回收且低脂的產品 題目 表&#xff1a;Products -------------------- | Column Name | Type | -------------------- | product_id | int | | low_fats | enum | | recyclable | enum | -------------------- product_id 是該表的主鍵&#xff08;具有…

CSS3 網格元素

CSS3 網格元素&#xff08;Grid Items&#xff09;是網格容器&#xff08;Grid Container&#xff09;的直接子元素&#xff0c;它們參與 CSS 網格布局&#xff0c;并根據網格容器的規則在網格中定位和排列。以下是對網格元素的詳細中文講解&#xff0c;涵蓋定義、相關屬性、用…

30天打牢數模基礎-決策樹講解

案例代碼一、代碼說明本代碼針對員工離職預測問題&#xff0c;使用CART決策樹算法&#xff08;基尼指數&#xff09;實現分類&#xff0c;并包含特征重要性評估和樹結構可視化。數據為模擬的10個員工樣本&#xff0c;特征包括工作年限、月薪、是否加班、團隊氛圍評分&#xff0…

React與jQuery全棧實戰指南

以下是為React工程師優化的jQuery全棧指南&#xff0c;結合Thymeleaf項目需求與React思維模式&#xff0c;整合核心概念、避坑策略及實戰技巧。內容依據官方文檔與多篇技術文章優化補充&#xff0c;保留原有框架并深化關鍵細節&#xff1a; ?一、jQuery核心設計哲學 vs React?…

Redis分布式鎖的學習(八)

一、分布式鎖 1.1、分布式鎖是什么&#xff1f; 是一種在分布式系統中協調多個進程/服務對共享資源進行互斥訪問的機制&#xff1b;確保在任意時刻&#xff0c;只有一個客戶端可以訪問資源。 1.2、為什么需要分布式鎖&#xff1f; 解決多個服務/進程對同共享資源競爭&…

spring的常用注解匯總

在 Spring 和 Spring Boot 框架中&#xff0c;有許多核心注解被廣泛應用。以下是常用的關鍵注解分類詳解&#xff1a;一、組件聲明與依賴注入注解作用示例Component通用組件聲明 (Bean 的泛化形式)Component public class ServiceImpl {...}Service標記服務層&#xff08;業務邏…

Claude4、GPT4、Kimi K2、Gemini2.5、DeepSeek R1、Code Llama等2025主流AI編程大模型多維度對比分析報告

2025主流AI編程大模型多維度對比分析報告引言&#xff1a;AI編程大模型的技術格局與選型挑戰一、核心模型概覽&#xff1a;技術定位與市場份額1.國際第一梯隊&#xff08;1&#xff09;Claude 4系列&#xff08;Anthropic&#xff09;&#xff08;2&#xff09;GPT-4.1&#xf…

Overleaf中下載.aux和.bbl文件

有些會議提交終稿的時候&#xff0c;可能會讓上傳.bbl和.aux文件&#xff0c;但是使用Overleaf下載下來的壓縮包中缺沒有這些文件在網上搜了一下都是用的舊版的Overleaf的教程&#xff0c;或者教程比較繁瑣&#xff0c;其實新版的Overleaf也可以直接下載 打開你的論文編譯好&am…

uniapp寫app做測試手機通知欄展示內容

uniapp寫app做測試手機通知欄展示內容 以下代碼&#xff1a;只是個簡單測試能不能給手機發送消息&#xff0c;能不能引導打開通知權限&#xff0c;能不能進行跳轉的功能, 增加 notify.js 以下文件 // 模擬本地通知功能 export function showNotification() {// 1. 檢查通知…

分布式云計算:未來計算架構的全新演進

隨著信息技術的不斷發展,尤其是云計算技術的飛速進步,企業和個人對計算資源的需求已經從傳統的單一數據中心向更為靈活、可擴展的分布式架構轉變。分布式云計算作為一種新興的云計算模型,旨在將計算資源和數據存儲分布在多個地理位置上,從而提供更加高效、安全和可靠的服務…

2025年海外短劇獨立站開發:H5+PC端雙平臺技術實踐與增長策略

引言在全球化內容消費浪潮下&#xff0c;海外短劇市場正經歷爆發式增長。據DataEye《2025H1海外微短劇行業數據報告》顯示&#xff0c;2025年海外短劇市場規模預計突破45億美元&#xff0c;其中東南亞、拉美等新興市場貢獻超30%增量。本文將以某頭部短劇平臺的雙平臺開發實踐為…

OpenAI發布ChatGPT Agent,AI智能體迎來關鍵變革

注&#xff1a;此文章內容均節選自充電了么創始人&#xff0c;CEO兼CTO陳敬雷老師的新書《GPT多模態大模型與AI Agent智能體》&#xff08;跟我一起學人工智能&#xff09;【陳敬雷編著】【清華大學出版社】 清華《GPT多模態大模型與AI Agent智能體》書籍配套視頻課程【陳敬雷…

企業級安全威脅檢測與響應(EDR/XDR)架構設計

在這個網絡威脅如洪水猛獸的時代&#xff0c;企業的安全防護不能再像守城門的老大爺一樣只會喊"什么人&#xff1f;口令&#xff01;"了。我們需要的是一套像FBI一樣具備全方位偵察能力的智能防護系統。 &#x1f4cb; 文章目錄 1. 什么是EDR/XDR&#xff1f;別被這…

Stream流-Java

Stream流的作用&#xff1a;結合了Lambda表達式&#xff0c;簡化集合&#xff0c;數組的操作Stream流的使用步驟&#xff1a;1. 先得到一條Stream流&#xff08;流水線&#xff09;&#xff0c;并把數據放上去獲取方式方法名說明單列集合default Stream<E> stream()Colle…

Leetcode 327. 區間和的個數

1.題目基本信息 1.1.題目描述 給你一個整數數組 nums 以及兩個整數 lower 和 upper 。求數組中&#xff0c;值位于范圍 [lower, upper] &#xff08;包含 lower 和 upper&#xff09;之內的 區間和的個數 。 區間和 S(i, j) 表示在 nums 中&#xff0c;位置從 i 到 j 的元素…

MinIO 版本管理實踐指南(附完整 Go 示例)

? 前言 在構建企業級對象存儲系統時,“對象的版本管理”是一個關鍵特性。MinIO 作為一款高性能、Kubernetes 原生的 S3 兼容對象存儲系統,也支持強大的版本控制功能。 本文將通過 Go 示例代碼 + 實操講解 的形式,手把手帶你掌握 MinIO 的版本控制能力,包括開啟版本控制、…

數組toString方法及類型檢測修復方案

在 JavaScript 中&#xff0c;數組的 toString() 方法被覆蓋&#xff08;重寫&#xff09;為返回數組元素的逗號分隔字符串&#xff0c;而不是原始的 [object Array] 類型標識。以下是詳細解釋和修復方案&#xff1a;問題原因Array.prototype.toString 被覆蓋數組繼承自 Object…

mysql索引底層B+樹

B樹勝出的關鍵特性&#xff1a;矮胖樹結構&#xff1a;3-4層高度即可存儲2000萬條記錄&#xff08;假設每頁存1000條&#xff09; 葉子鏈表&#xff1a;所有數據存儲在葉子節點&#xff0c;并通過雙向鏈表連接 非葉導航&#xff1a;非葉子節點僅存儲鍵值&#xff0c;不保存數據…

AI開放課堂:釘釘MCP開發實戰

我們正處在AI技術爆發的時代&#xff0c;也處于企業數字化蓬勃發展的時代。如何利用AI技術&#xff0c;突破模型自身知識的局限&#xff0c;安全、高效地與外部世界連接和交互&#xff0c;是當前所有AI開發者在企業數字化中面臨的問題之一。 MCP&#xff08;Model Context Prot…