文件比对标红显示

既然你已经有了工程文件的结构数据(比如是从 project.config.json 读取出来的树形结构),现在的核心任务是:验证这些路径在磁盘上是否真的存在,并根据结果更新 UI。

这是一个典型的 “元数据” vs “物理数据” 的校验场景。

为了保证性能(避免成百上千次 IPC 通信),我们应该采用 “批量校验” 的策略。

electron-vite IDE左侧读取工程文件

这是一个非常硬核且实用的需求。要实现类似 VS Code / Visual Studio 的工程文件资源管理器,我们需要打通 Electron 的 Main Process (Node.js fs 能力)Renderer Process (Vue 组件交互)

由于代码量较大,我将分为 后端 (IPC/Node)前端 (Vue 组件) 两部分来构建。

多窗口事件总线怎么处理

问题

我现在做的是多窗口应用(基于electron-vite,vue3,和dokeview),现在有一个场景:我们原项目里面多出地方使用的事件总线模式,在组件挂载的时候注册事件,在组件销毁的时候off事件,现在改成多窗口应用后,就出现了打开了多个注册事件的窗口,事件触发的时候会触发多次,事件关闭的时候就全都关闭了。这种情况 有什么好的解决方案吗?

electron多窗口状态同步 插件pinia-plugin-electron-share升级版

前言

通过indexDb存储pinia的相关数据。传输的时候不用传输整个数据

核心思想转变:
之前的模式是 “数据跟随消息” (Push Data),现在的模式是 “消息通知,数据自取” (Signal & Pull)

  1. 写入方:Store 变更 -> 写入 IndexedDB -> 发送 “数据已更新” 的信号(不带数据)。
  2. 接收方:收到信号 -> 从 IndexedDB 读取最新数据 -> 更新 Store。
  3. 初始化:新窗口启动 -> 请求初始化 -> 老窗口强制将内存数据刷入 IndexedDB -> 发送 “准备好了” -> 新窗口从 DB 读取。

这样做的好处是 BroadcastChannel 极其轻量,不再受数据大小限制,且数据持久化由 IndexedDB 承担。

BroadcastChannel 握手机制的方法

BroadcastChannel 握手机制的方法实现

使用场景,dokeview tab拖出来窗口外第一次创建窗口的时候传递参数。

将这种“握手”逻辑封装成通用的工具函数,可以大大减少重复代码,并保证逻辑的健壮性。

封装了一个类型安全、支持超时控制的 WindowSync 工具库。

监听窗口创建完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// src/main/index.ts

// 1. 监听新窗口创建请求 (拦截层)
mainWindow.webContents.setWindowOpenHandler((details) => {
// details.url 包含了新窗口的 URL
// details.frameName 可能是 dockview 指定的名字
console.log('⚡️ 检测到 Tab 被拖出,正在请求创建窗口:', details.url)

// 你可以在这里判断 url 是否包含特定的 query 参数,来确定这是 dockview 的弹窗

return {
action: 'allow',
overrideBrowserWindowOptions: {
// 在这里强制指定新窗口的样式
autoHideMenuBar: true,
webPreferences: {
preload: join(__dirname, '../preload/index.js'), // 别忘了 preload
backgroundThrottling: false,
// ...其他配置
}
}
}
})

// 2. 监听窗口创建完成 (结果层)
mainWindow.webContents.on('did-create-window', (childWindow, details) => {
console.log('✅ 新窗口实例已创建 (Tab 弹出成功)')

// 业务场景:你可能想告诉主渲染进程“有个子窗口诞生了”
mainWindow.webContents.send('popout-window-created', {
id: childWindow.id,
title: childWindow.getTitle()
})

// 业务场景:监听子窗口的关闭,做一些清理工作
childWindow.on('closed', () => {
console.log('❌ 子窗口已关闭')
mainWindow.webContents.send('popout-window-closed', { id: childWindow.id })
})
})

上传到npm仓库

发布 npm 包不仅仅是把代码放上去,还需要考虑 构建规范 (ESM/CJS)类型定义 (TypeScript .d.ts)Peer Dependencies 以及 扩展性

既然我们要把它做成一个通用的 pinia-plugin-electron-share,我们需要让它支持配置(比如自定义 Channel 名称),并且具备完善的工程化结构。

这里是可以直接 npm publish 的完整工程代码结构

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器