

作者:VON HarmonyOS 初级开发者|CSDN 新星创作者(Java/Web 领域) 专栏链接:Electron for OpenHarmony
在日常开发或办公中,你是否曾因误操作丢失了刚复制的重要内容?是否希望像 macOS 的“通用剪贴板”或 Windows 的“剪贴板历史”一样,随时回溯最近复制的文本?
本文将带你从零构建一个 跨平台剪贴板历史管理器,它能:
这个项目融合了 系统级 API 调用、事件监听、数据持久化与安全 IPC 通信,是 Electron 中高级实战的典型代表。
优势 | 说明 |
|---|---|
✅ 真实用户痛点 | 解决“复制即丢失”的高频问题 |
✅ 系统能力集成 | 使用 clipboard 模块监听全局剪贴板 |
✅ 状态管理实践 | 实现内存缓存 + 本地存储(可选) |
✅ 鸿蒙迁移潜力大 | OpenHarmony 提供 @ohos.clipboard 能力 |
💡 此项目是学习 Electron 后台能力 + 用户交互闭环 的理想案例。
clipboard-history/
├── main.js # 主进程:监听剪贴板 + 管理历史
├── preload.js # 安全桥接:暴露获取/粘贴历史接口
├── index.html # 渲染界面:展示历史列表
└── package.json # 依赖配置mkdir clipboard-history && cd clipboard-history
npm init -y
npm install electron --save-devpackage.json{
"name": "clipboard-history",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^33.0.0"
}
}main.js —— 主进程:核心逻辑const { app, BrowserWindow, ipcMain, clipboard, nativeImage } = require('electron');
const path = require('path');
// 最多保存 10 条历史
const MAX_HISTORY = 10;
let history = [];
let lastContent = '';
function createWindow() {
const win = new BrowserWindow({
width: 500,
height: 400,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
},
resizable: false
});
win.loadFile('index.html');
}
// 监听剪贴板变化(每秒轮询)
function watchClipboard() {
setInterval(() => {
try {
const content = clipboard.readText().trim();
if (content && content !== lastContent) {
// 去重 & 限制长度
if (!history.some(item => item.text === content)) {
history.unshift({ text: content, time: Date.now() });
if (history.length > MAX_HISTORY) history.pop();
lastContent = content;
// 通知渲染进程更新(可选)
}
}
} catch (err) {
console.warn('剪贴板读取失败:', err.message);
}
}, 1000);
}
// IPC 接口:获取历史
ipcMain.handle('get-clipboard-history', () => {
return history;
});
// IPC 接口:粘贴指定内容
ipcMain.on('paste-text', (event, text) => {
clipboard.writeText(text);
});
app.whenReady().then(() => {
createWindow();
watchClipboard(); // 启动监听
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});⚠️ 注意:Electron 无法通过事件监听剪贴板变化,需使用轮询(这是当前限制)。
preload.js —— 安全桥接层const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('clipAPI', {
getHistory: () => ipcRenderer.invoke('get-clipboard-history'),
pasteText: (text) => ipcRenderer.send('paste-text', text)
});index.html —— 用户界面<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>剪贴板历史</title>
<style>
body {
font-family: system-ui, sans-serif;
margin: 0;
padding: 16px;
background: #fff;
color: #333;
}
h2 {
text-align: center;
margin-top: 0;
color: #0d6efd;
}
.history-list {
max-height: 300px;
overflow-y: auto;
}
.item {
padding: 10px;
border-bottom: 1px solid #eee;
cursor: pointer;
transition: background 0.2s;
}
.item:hover {
background: #f0f8ff;
}
.text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
}
.time {
font-size: 12px;
color: #888;
margin-top: 4px;
}
</style>
</head>
<body>
<h2>📋 剪贴板历史(最多10条)</h2>
<div class="history-list" id="list"></div>
<script>
async function renderHistory() {
const list = document.getElementById('list');
const history = await window.clipAPI.getHistory();
if (history.length === 0) {
list.innerHTML = '<div style="text-align:center;color:#999;">暂无历史记录</div>';
return;
}
list.innerHTML = history.map(item => `
<div class="item" onclick="paste('${item.text.replace(/'/g, "\\'")}')">
<div class="text">${item.text}</div>
<div class="time">${new Date(item.time).toLocaleTimeString()}</div>
</div>
`).join('');
}
function paste(text) {
window.clipAPI.pasteText(text);
alert('✅ 已复制到剪贴板!');
}
// 初始加载
renderHistory();
// 每3秒刷新一次(简化版)
setInterval(renderHistory, 3000);
</script>
</body>
</html>✨ 特性:
npm start
✅ 成功!你拥有了自己的“剪贴板时光机”。
OpenHarmony 从 API 9 开始支持剪贴板能力:
import clipboard from '@ohos.clipboard';
// 读取文本
const text = clipboard.getTextSync();
// 写入文本
clipboard.setTextSync('Hello Harmony');Electron 方案 | OpenHarmony 替代 |
|---|---|
轮询 clipboard.readText() | 使用 clipboard.on('update', callback)(若支持)或定时轮询 |
主进程管理历史 | 在 ArkTS 中维护 @State history: Array<string> |
Web 界面交互 | 保留 index.html,通过 WebController.callMethod 注入数据 |
🌉 示例:在鸿蒙中,可将历史管理逻辑放在 Ability 中,
Web组件仅负责展示和触发粘贴。

真机测试成功

electron-store 保存历史到磁盘;Ctrl+Shift+V);剪贴板历史管理器虽小,却体现了 系统集成 + 用户体验 + 安全架构 的完整闭环。它不仅是效率利器,更是通往更复杂桌面应用的阶梯。
更重要的是,它的核心逻辑——监听系统事件 → 缓存数据 → 提供交互——正是跨端开发的通用范式。
当你未来面对 OpenHarmony、Tauri 或 Flutter Desktop 时,这种模式将反复出现。
每一次复制,都不该被遗忘;每一次粘贴,都值得被设计。