electron-vChat聊天是一个基于electron+electron-vue+vue+vuex+Nodejs+vue-router等技术开发的高仿微信pc客户端界面聊天室项目,实现消息发送/表情,图片/视频预览,拖拽上传/粘贴截图发送/微信dll截图,右键菜单、朋友圈/红包/换肤等功能。css
如上图:能够自由切换桌面端聊天背景皮肤html
Electron 是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。
https://electronjs.org/
至于如何搭建开发环境及使用electron-vue,可自行去查阅官网及搜资料
基于vue语法来构造 electron 应用程序的样板代码。
https://electron.org.cn/vue/i...
https://simulatedgreg.gitbook...vue
经过electron里的BrowserWindow对象建立和控制浏览器窗口
src目录下有main、renderer两个文件夹,分别是主进程及渲染进程,配置窗口修改src/main/index.js文件便可。ios
let mainWin let tray let forceQuit = false let logined = false /** * 建立主窗口============================= */ function createMainWin() { mainWin = new BrowserWindow({ // 背景颜色 // backgroundColor: '#ebebeb', width: Common.WIN_SIZE_MAIN.width, height: Common.WIN_SIZE_MAIN.height, title: Common.WIN_TITLE, useContentSize: true, autoHideMenuBar: true, // 无边框窗口 frame: false, resizable: true, // 窗口建立的时候是否显示. 默认值为true show: false, webPreferences: { // devTools: false, webSecurity: false } }) mainWin.setMenu(null) mainWin.loadURL(Common.WIN_LOAD_URL()) mainWin.once('ready-to-show', () => { mainWin.show() mainWin.focus() }) // 点击关闭最小到托盘判断 mainWin.on('close', (e) => { if(logined && !forceQuit) { e.preventDefault() mainWin.hide() }else { mainWin = null app.quit() } }) ... apptray.createTray() } app.on('ready', createMainWin) app.on('activate', () => { if(mainWin === null) { createMainWin() } }) ...
electron建立托盘图标、托盘图标闪烁、最小化到托盘、托盘右键git
/** * 托盘图标事件 */ let flashTrayTimer = null let trayIco1 = `${__static}/icon.ico` let trayIco2 = `${__static}/empty.ico` let apptray = { // 建立托盘图标 createTray() { tray = new Tray(trayIco1) const menu = Menu.buildFromTemplate([ { label: '打开主界面', icon: `${__static}/tray-ico1.png`, click: () => { if(mainWin.isMinimized()) mainWin.restore() mainWin.show() mainWin.focus() this.flashTray(false) } }, { label: '关于', }, { label: '退出', click: () => { if(process.platform !== 'darwin') { mainWin.show() // 清空登陆信息 mainWin.webContents.send('clearLoggedInfo') forceQuit = true mainWin = null app.quit() } } }, ]) tray.setContextMenu(menu) tray.setToolTip('electron-vchat v1.0.0') // 托盘点击事件 tray.on('click', () => { if(mainWin.isMinimized()) mainWin.restore() mainWin.show() mainWin.focus() this.flashTray(false) }) }, // 托盘图标闪烁 flashTray(flash) { let hasIco = false if(flash) { if(flashTrayTimer) return flashTrayTimer = setInterval(() => { tray.setImage(hasIco ? trayIco1 : trayIco2) hasIco = !hasIco }, 500) }else { if(flashTrayTimer) { clearInterval(flashTrayTimer) flashTrayTimer = null } tray.setImage(trayIco1) } }, // 销毁托盘图标 destroyTray() { this.flashTray(false) tray.destroy() tray = null } }
点击窗口关闭,监听close事件,判断是否最小化到托盘web
// 点击关闭最小到托盘判断 mainWin.on('close', (e) => { if(logined && !forceQuit) { e.preventDefault() mainWin.hide() }else { mainWin = null app.quit() } })
/** * @Desc 主入口页面JS * @about Q:282310962 wx:xy190310 */ import Vue from 'vue' import axios from 'axios' import App from './App' import router from './router' import store from './store' // 引入组件配置 import $components from './components' Vue.use($components) if (!process.env.IS_WEB) Vue.use(require('vue-electron')) Vue.http = Vue.prototype.$http = axios /* eslint-disable no-new */ new Vue({ components: { App }, router, store, template: '<App/>' }).$mount('#app')
主窗口页面分为侧边栏+主布局,主布局顶部里含有最大/小化、关闭按钮vue-router
<template> <div id="app"> <div class="elv-container" :style="$store.state.winSkin && {'background-image': 'url('+$store.state.winSkin+')'}"> <div class="elv-wrapper flexbox"> <!-- //侧边栏 --> <side-bar v-if="!$route.meta.hideSideBar" /> <!-- //主布局 --> <div class="elv-mainbx flex1 flexbox flex-col"> <!-- ...顶部按钮 --> <win-bar /> <keep-alive> <router-view></router-view> </keep-alive> </div> </div> </div> </div> </template>
配置frame: false就能实现无边框窗体,拖动窗口功能需另行处理vuex
设置css -webkit-app-region: drag;
就能实现拖动窗口
设置-webkit-app-region: drag后,下面的元素不能点击操做,可经过设置需点击元素no-drag便可。axios
顶部winbar.vue组件segmentfault
import { app, remote, ipcRenderer } from 'electron' import { mapState, mapMutations } from 'vuex' let currentWin = remote.getCurrentWindow() export default { props: { title: String, }, data () { return {// 是否置顶 isAlwaysOnTop: false, // 窗口是否能够最小化 isMinimizable: true, // 窗口是否能够最大化 isMaximizable: true, } }, computed: { ...mapState(['isWinMaxed']) }, mounted() {if(!currentWin.isMinimizable()) { this.isMinimizable = false } if(!currentWin.isMaximizable()) { this.isMaximizable = false } if(this.isWinMaxed && currentWin.isMaximizable()) { currentWin.maximize() } // 监听是否最大化 currentWin.on('maximize', () => { this.SET_WINMAXIMIZE(true) }) currentWin.on('unmaximize', () => { this.SET_WINMAXIMIZE(false) }) }, methods: { ...mapMutations(['SET_WINMAXIMIZE']), // 置顶窗口 handleFixTop() { this.isAlwaysOnTop = !this.isAlwaysOnTop currentWin.setAlwaysOnTop(this.isAlwaysOnTop) }, // 最小化 handleMin() { currentWin.minimize() }, // 最大化 handleMax() { if(!currentWin.isMaximizable()) return if(currentWin.isMaximized()) { currentWin.unmaximize() this.SET_WINMAXIMIZE(false) }else { currentWin.maximize() this.SET_WINMAXIMIZE(true) } }, // 关闭 handleQuit() { currentWin.close() } } }
vue如何实现编辑框contenteditable光标处插入动态表情,这里很少介绍,能够去看以前的一篇分享文章。
electron+vue实现div contenteditable功能|截图
好了,基于electron+vue开发仿微信桌面聊天实例就分享到这里,但愿能有点点帮助!!💪💪
最后分享个uniapp+vue实例项目
uniapp即时聊天|vue+uniapp仿微信app聊天实例|uniapp仿微信界面