0、相关文档:
eletron 文档:
http://electronjs.org/docs/
模版 electron-vite 文档:
https://cn.electron-vite.org/
axios 文档:
https://www.axios-http.cn/docs/interceptors

1、环境搭建
a, 依赖按照

npm install npx -g
npx degit alex8088/electron-vite-boilerplate lkk-clk

npm install vue-router -S

// 状态管理
npm install pinia -S
// 状态持久化
npm install pinia-plugin-persist

状态管理:

import {createPinia} from 'pinia';
// 持久化
// src/rederer/main.ts
import piniaPluginPersist from 'pinia-plugin-persist'
const store = createPinia()
store.use(piniaPluginPersist)
createApp(App).use(Router).use(store).mount('#app')

http请求:

npm i axios -S

UI框架ElementPlus安装:

// 引入element-plus
npm i element-plus --save
// 按需引入
npm install -D unplugin-vue-components unplugin-auto-import
// icon图标安装
npm install @element-plus/icons-vue
// src/rederer/main.ts 引入
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
const app = createApp(App);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    app.component(key, component)
}
app.use(Router).use(store).mount('#app')

// scss
npm i -D sass sass-loader

2、默认打开调试窗口
main/index.ts
mainWindow.webContents.openDevTools();

3、渲染窗口向主进程通讯
a、渲染窗口事件
electron.ipcRenderer.invoke("webOpen",{k:123})

b、主进程收到消息 src/main/index
ipcMain.handle('webOpen',(event,msg)=>{

// console.log(event);
console.log(msg);

})

3、主进程打开一个新窗口

ipcMain.handle('webOpen',(event,msg)=>{

// console.log(event);
console.log(msg);
if(msg.name == 'list'){
  const listWindow = new BrowserWindow({
    width: 500,
    height: 400,
    show: false,
    autoHideMenuBar: true,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  });
  listWindow.on('ready-to-show',()=>{listWindow.show()});
  listWindow.loadURL(process.env['ELECTRON_RENDERER_URL']+'/#/list')
}

})

4、隐藏窗口标题栏:
titleBarStyle:'hidden'
窗口可拖拽样式一:
--webkit-app-region:drag;

窗口可拖拽二:
// 需要拖拽的页面
let isKeyDown = ref<boolean>(false);
let dinatesX = ref<number>(0);
let dinatesY = ref<number>(0);

const mousedown = ( event )=>{

isKeyDown.value = true;
dinatesX.value = event.x;
dinatesY.value = event.y;

document.onmousemove = (ev) => {
    if(isKeyDown.value ){
        const x = ev.screenX - dinatesX.value;
        const y = ev.screenY - dinatesY.value;
        //给主进程传入坐标
        let data = {
            appX:x,
            appY:y
        }
        electron.ipcRenderer.invoke('custom-adsorption',data);
    }
};
document.onmouseup = () => {
    isKeyDown.value = false
};

}
// src/main/index
// 渲染进程拖拽窗口
ipcMain.handle('custom-adsorption',(event,res) => {

let x = res.appX;
let y = res.appY;
mainWindow.setPosition( x , y )

})

5、创建子窗口,多次点击不重复创建。
// src/main/index
/ 创建子窗口并不重复创建 Start /
// 子窗口对象2
const childWindow = <{allowQuitting:boolean,isShow:boolean;listWindow:null|BrowserWindow}>{
allowQuitting: false, // 是否退出营运
isShow: true, // 显示隐藏窗口
listWindow: null // 创建窗口对象
}
// 显示
const showWindow = ()=>{
if(childWindow.listWindow&&!childWindow.listWindow.isDestroyed()){

childWindow.isShow = true;
childWindow.listWindow.show();

}
}
// 隐藏
const hideWindow = ()=>{
if(childWindow.listWindow&&!childWindow.listWindow.isDestroyed()){

childWindow.isShow = false;
childWindow.listWindow.hide();

}
}
// 关闭
childWindow.listWindow?.on('close',()=>{
// 如果主进程未停止,则隐藏窗口
if(childWindow.allowQuitting==false){

hideWindow();

}else{

childWindow.listWindow=null;

}
})
// 创建子窗口
function createListWindow(): void {
// 创建窗口
childWindow.listWindow = new BrowserWindow({

width: 400,
height: 100,
show: false,
frame: false, // 无边框窗口
resizable: false, // 无法拉大缩小窗口
alwaysOnTop: true, // 置顶窗口
transparent: true, // 窗口透明
hasShadow: false, // 祛除阴影
autoHideMenuBar: true,
...(process.platform === 'linux' ? { icon } : {}),
webPreferences: {
  preload: join(__dirname, '../preload/index.js'),
  sandbox: false
}

});
// 显示窗口
childWindow.listWindow.on('ready-to-show',()=>{

childWindow.listWindow?.show();
// 子窗口位置
let winHeight = screen.getPrimaryDisplay().bounds.height;
childWindow.listWindow?.setBounds({
  y: winHeight-150
})

})
// 对应的页面
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {

childWindow.listWindow.loadURL(process.env['ELECTRON_RENDERER_URL']+'/#/list')

} else {

childWindow.listWindow.loadFile(join(__dirname, '../renderer/index.html'))

}
}
ipcMain.handle('new-list',(event,res)=>{
// console.log('custom-list',childWindow.listWindow);
if(childWindow.listWindow==null){

createListWindow();

}else{

if(childWindow.isShow){
  hideWindow();
}else{
  showWindow();
}

}
})
if(childWindow){
ipcMain.handle('close-list',()=>{

hideWindow();

})
}
let isKiosk:boolean;
if(childWindow){
ipcMain.handle('kiosk-list',(e,res)=>{

console.log(res.isKiosk)    
isKiosk=res.isKiosk;

})
}
// 拖拽
if(childWindow){
ipcMain.handle('custom-list',(event,res) => {

if(!isKiosk){
      let x = res.appX;
      let y = res.appY;
  childWindow.listWindow?.setPosition( x , y )
}

})
}
/ 创建子窗口并不重复创建 End /

6、窗口配置
// src/main/index
childWindow.listWindow = new BrowserWindow({

width: 400,
height: 100,
show: false,
frame: false, // 无边框窗口
resizable: false, // 无法拉大缩小窗口
alwaysOnTop: true, // 置顶窗口
transparent: true, // 窗口透明
hasShadow: false, // 祛除阴影
autoHideMenuBar: true,
...(process.platform === 'linux' ? { icon } : {}),
webPreferences: {
  preload: join(__dirname, '../preload/index.js'),
  sandbox: false
}

});

7、关闭窗口
// BrowserWindow 实例
close 方法用于关闭窗口,可以通过监听 close 事件来执行一些自定义操作,并有机会取消关闭操作。
destroy 方法用于彻底销毁一个窗口,不会触发 close 事件,并立即释放与窗口相关的所有资源。
// app import electron
app.quit() 方法用于退出整个 Electron 应用程序,可以通过监听 before-quit 事件来执行一些预处理操作。
app.exit() 方法用于立即终止整个 Electron 应用程序的进程,不会触发任何事件。

8、最小化、最大化

9、打包

最后编辑:2026年01月22日 ©著作权归作者所有

发表评论