方便以后定制化使用,学习记录一下。
话不多说,先看看效果吧。
效果
版本
- electron ^13.0.0
知识点
Vue 相互通讯 Electron 标题栏主要逻辑代码
新建public\preload.js
文件,用于前端全局发送和监听消息。
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
minimize: () => ipcRenderer.send('minimize'),
windowization: () => ipcRenderer.send('windowization'),
maximize: () => ipcRenderer.send('maximize'),
quit: () => ipcRenderer.send('quit'),
onIsMaximizable: (callback) => ipcRenderer.on('is-maximizable', callback)
})
修改src\background.js
文件,用于Electron接受发送消息。
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
// 框架隐藏
frame: false,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
preload: process.env.WEBPACK_DEV_SERVER_URL ? path.join(__dirname, 'bundled', 'preload.js') : path.join(__dirname, 'preload.js')
}
})
win.on('maximize', (event) => {
console.log("窗口最大化")
win.webContents.send('is-maximizable', true)
})
win.on('resize', (event) => {
console.log("窗口还原");
win.webContents.send('is-maximizable', win.isMaximized())
})
}
ipcMain.on('minimize', (event) => {
win.minimize()
})
ipcMain.on('quit', (event) => {
app.quit()
})
ipcMain.on('maximize', (event) => {
win.maximize()
})
ipcMain.on('windowization', (event) => {
win.restore();
})
关于打包构建调试,preload.js
加载路径可能不同,所以需要根据不同环境进行判断。
preload: process.env.WEBPACK_DEV_SERVER_URL ? path.join(__dirname, 'bundled', 'preload.js') : path.join(__dirname, 'preload.js')
新建src\components\TitleBar.vue
组件,标题栏样式和调用preload.js
中的方法。
<template>
<div class="title-bar">
<div class="title-bar__left">
<img class="title-bar__logo" src="../assets/logo.png" />
<div class="title-bar__title">Vue 桌面程序</div>
</div>
<div class="title-bar__right" :style="{ '-webkit-app-region': 'no-drag' }">
<div class="title-bar__icon" @click="minimize">
<i class="iconfont icon-window-min_line"></i>
</div>
<div class="title-bar__icon" @click="windowization" v-show="isMaximizable">
<i class="iconfont icon-window-window_line"></i>
</div>
<div class="title-bar__icon" @click="maximize" v-show="!isMaximizable">
<i class="iconfont icon-window-max_line"></i>
</div>
<div class="title-bar__icon" @click="quit">
<i class="iconfont icon-delete_line"></i>
</div>
</div>
</div>
</template>
<script>
export default {
created() {
this.onIsMaximizable();
},
data() {
return {
isMaximizable: false,
};
},
methods: {
minimize() {
console.log("最小化");
window.electronAPI.minimize();
},
windowization() {
console.log("窗口化");
window.electronAPI.windowization();
},
maximize() {
console.log("最大化");
window.electronAPI.maximize();
},
quit() {
console.log("退出");
window.electronAPI.quit();
},
onIsMaximizable() {
window.electronAPI.onIsMaximizable((event, isMaximizable) => {
console.log("监听窗口的变化", isMaximizable);
this.isMaximizable = isMaximizable;
});
},
},
};
</script>
<style lang="scss" scoped>
@import url("../assets/css/iconfont.css");
.title-bar {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #ddd;
height: 30px;
-webkit-app-region: drag;
.title-bar__logo {
width: 25px;
height: 25px;
margin-left: 10px;
}
.title-bar__title {
margin-left: 6px;
}
.title-bar__right {
margin-right: 10px;
}
.title-bar__icon {
margin-left: 10px;
}
.title-bar__left,
.title-bar__right {
display: flex;
align-items: center;
}
.title-bar__icon {
display: flex;
:active {
background-color: #999;
}
}
}
</style>
在src\App.vue
页面中引用。
需要调整好样式不然滚动条就…🏊
<template>
<div id="app">
<title-bar></title-bar>
<div class="app-body">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view />
</div>
</div>
</template>
<script>
import TitleBar from "./components/TitleBar.vue";
export default {
components: { TitleBar },
};
</script>
<style lang="scss">
body {
margin: 0;
overflow: hidden;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
overflow: hidden;
height: 100vh;
}
.app-body {
overflow: auto;
height: 100%;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
注意:修改完后记得先执行yarn run electron:build
,直接执行yarn run electron:serve
,对应的preload.js
可能会是旧的文件。
隐藏菜单栏
修改src\background.js
文件
import { Menu } from "electron";
// 禁用菜单栏
Menu.setApplicationMenu(null);
隐藏标题栏
修改src\background.js
文件
import { BrowserWindow } from "electron";
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
// 框架隐藏
frame: false,
webPreferences: {
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
}
})
// 略
}
设置拖动窗体
修改src\App.vue
文件
-webkit-app-region: drag 用于设定该部分为可拖动区域
-webkit-app-region: no-drag 用于设定该部分为不可拖动区域
<div id="app" style="-webkit-app-region: drag"></div>
相关文档
https://www.electronjs.org/zh/docs/latest/tutorial/context-isolation
源码
可能会有点乱,大多重点代码都在文章里了。
https://github.com/linyisonger/Vue.Examples