项目说明:
electron-vChat聊天是一个基于electron+electron-vue+vue+vuex+Nodejs+vue-router等技术开发的高仿微信pc客户端界面聊天室项目,实现消息发送/表情,图片/视频预览,拖拽上传/粘贴截图发送/微信dll截图,右键菜单、朋友圈/红包/换肤等功能。
预览图:
技术框架:
- 运用技术:electron + electron-vue + vue
- 状态管理:Vuex
- 地址路由:Vue-router
- 字体图标:阿里iconfont字体图标库
- 弹窗插件:wcPop
- 打包工具:electron-builder
- 图片预览:vue-photo-preview
- 视频组件:vue-video-player
如上图:可以自由切换桌面端聊天背景皮肤
Electron 是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。
https://electronjs.org/
至于如何搭建开发环境及使用electron-vue,可自行去查阅官网及搜资料
基于vue语法来构造 electron 应用程序的样板代码。
https://electron.org.cn/vue/i...
https://simulatedgreg.gitbook...
electron主进程:创建及配置
通过electron里的BrowserWindow对象创建和控制浏览器窗口
src目录下有main、renderer两个文件夹,分别是主进程及渲染进程,配置窗口修改src/main/index.js文件即可。
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创建托盘图标、托盘图标闪烁、最小化到托盘、托盘右键
/**
* 托盘图标事件
*/
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事件,判断是否最小化到托盘
// 点击关闭最小到托盘判断
mainWin.on('close', (e) => {
if(logined && !forceQuit) {
e.preventDefault()
mainWin.hide()
}else {
mainWin = null
app.quit()
}
})
electron渲染进程:主入口页面配置
/**
* @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')
主窗口页面分为侧边栏+主布局,主布局顶部里含有最大/小化、关闭按钮
<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>
electron无边框窗口实现拖动、最大/小化、关闭功能
配置frame: false就能实现无边框窗体,拖动窗口功能需另行处理
- 通过mousedown、mousemove等事件处理
- 设置需要拖动区css属性 -webkit-app-region
设置css -webkit-app-region: drag;
就能实现拖动窗口
设置-webkit-app-region: drag后,下面的元素不能点击操作,可通过设置需点击元素no-drag即可。
顶部winbar.vue组件
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()
}
}
}
electron编辑器光标处插入表情、div可编辑contenteditable="true"双向绑定 、electron截图功能
vue如何实现编辑框contenteditable光标处插入动态表情,这里不多介绍,可以去看之前的一篇分享文章。
electron+vue实现div contenteditable功能|截图
好了,基于electron+vue开发仿微信桌面聊天实例就分享到这里,希望能有点点帮助!!💪💪
最后分享个uniapp+vue实例项目
uniapp即时聊天|vue+uniapp仿微信app聊天实例|uniapp仿微信界面