Recently, I have been working on electron technology. Since electron is a framework for creating native programs using JavaScript, HTML, CSS and other Web technologies, I can use VUE to develop pages, and I have used VUE to develop chat instances before. So the electron+ VUE technology is adopted for project selection.

ElectronVchat is a simulated wechat desktop chat IM project based on electron+vue+electron-vue+vuex+ electron-Builder + vue-Router technology, with message sending/expression, picture/video preview, Drag upload/paste screenshots send/wechat DLL screenshots, right-click menu, circle of friends/red envelope/skin and other functions.

Vue chat room | | h5 + vue imitation WeChat chat screen vue imitation WeChat

Technology stack:

  • Application technology: electron + electron- VUE + VUE
  • Status management: Vuex
  • Address routing: vue-router
  • Font icon: Ali Iconfont font icon library
  • Popover plugin: wcPop
  • Packing tool: electron- Builder
  • Image preview: Vue-photo-preview
  • Video component: VUe-video-player

You can refer to the official website for electron installation and configuration and environment construction of the electron vUE project.

Simulatedgreg. Gitbooks. IO/electron – vu…

Github.com/SimulatedGR…

The electron main process creates a window

After the project-electron vue is built, the main process entry page is SRC /main/index.js

Through electron provide BrowserWindow object creation form, detailed configuration on BrowserWindow can see official introduction: electronjs.org/docs/api/br…

/** * @desc mainline Create by Andy on 2019/12/26 * @about Q: 282310962 wx: xy190310 */ import { BrowserWindow, app, ipcMain, Tray, Menu} from 'electron' import Common from './utils/ Common '/** * Set' __static 'path to static files in production * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html */ if (process.env.NODE_ENV ! == 'development') { global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')} let mainWin let tray let forceQuit = false let logined = false */ function createMainWin() { MainWin = new BrowserWindow({// backgroundColor // backgroundColor: '#ebebeb', width: common.win_size_main. width, height: Common.win_size_main. height, title: common.win_title, useContentSize: true, autoHideMenuBar: true, // Unframed window frame: False, resizable: true, // Whether the window is displayed when it is created. The default is 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 ()}) // Judge to minimize the system tray mainwin.on ('close', (e) => {if(logined &&! forceQuit) { e.preventDefault() mainWin.hide() }else { mainWin = null app.quit() } }) initialIPC() } app.on('ready', createMainWin) app.on('activate', () => { if(mainWin === null) { createMainWin() } }) app.on('before-quit', () => { forceQuit = true }) app.on('window-all-closed', () => { if(process.platform ! == 'darwin') { app.quit() } }) ...Copy the code

Electron realizes tray icon and flashing effect

/** * tray icon event */ let flashTrayTimer = null let trayIco1 = '${__static}/icon.ico' let trayIco2 = '${__static}/empty.ico' CreateTray () {tray = new Tray(trayIco1) const menu = menu. buildFromTemplate([{label: 'open the main interface, the icon: ` ${__static} / tray - ico1. PNG `, click: () => { if(mainWin.isMinimized()) mainWin.restore() mainWin.show() mainWin.focus() this.flashTray(false) } }, { label: 'About ',}, {label:' exit ', 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 click event tray.on('click', () => { if(mainWin.isMinimized()) mainWin.restore() mainWin.show() mainWin.focus() this.flashTray(false) }) }, FlashTray (bool) {let hasIco = false if(bool) {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}}Copy the code

Electron renderer directory page configuration

Introduce common components, third-party components, and page styles

Import winBar from './components/ winBar 'import sideBar from './components/ sideBar' / / introducing the common style import '. / assets/fonts/iconfont. CSS 'import'. / assets/CSS/reset. CSS 'import'. / assets/CSS/layout. CSS '/ / Introduce popup window wcPop import wcPop from '/ assets/js/wcPop wcPop' import '. / assets/js/wcPop/skin/wcPop. CSS '/ / Vue-photo-preview import photoView from 'vue-photo-preview' import 'vue-photo-preview/dist/skin.css' // Vue -video-player import videoPlayer from 'vue-video-player' import 'video.js/dist/video-js.css' const install = Vue.component('win-bar', winBar) Vue.component('side-bar', sideBar) Vue. Use (photoView, photoView) {// loop: false, // loop // fullscreenEl: true, // fullscreen // arrowEl: True, // left and right buttons}) vue. use(videoPlayer)} export default installCopy the code

The application of VUex in electron is basically the same as that of VUE, which will not be introduced here.

◆ The electron customized Max/miniaturization, close button, no frame window

After frame: false is configured in electron, the window will be displayed with no border, and the original top action bar will be removed, requiring custom configuration.

import { app, remote, ipcRenderer } from 'electron' import { mapState, mapMutations } from 'vuex' let currentWin = remote.getCurrentWindow() export default { props: { title: String,}, data () {return {// whether isAlwaysOnTop: false, // whether window can minimize isMinimizable: True, // Whether a window can be maximized 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()} // Whether to maximize currentwin. on('maximize', () => { this.SET_WINMAXIMIZE(true) }) currentWin.on('unmaximize', () => { this.SET_WINMAXIMIZE(false) }) }, methods: {... MapMutations (['SET_WINMAXIMIZE']), // Top window handleFixTop() {this.isalwaysonTop =! Enclosing isAlwaysOnTop currentWin. SetAlwaysOnTop (enclosing isAlwaysOnTop)}, / / minimize handleMin () {currentWin. Minimize ()}, // maximize handleMax() {if(! currentWin.isMaximizable()) return if(currentWin.isMaximized()) { currentWin.unmaximize() this.SET_WINMAXIMIZE(false) }else {currentwin. maximize() this.set_winmaximize (true)}}, // Close handleQuit() {currentwin. close()}}Copy the code

The project uses the -webkit-app-region: drag setting for local drag

_** Note: ** Default -webkit-app-region: drag, the following elements can not be clicked, can be set to no-drag element. _

The electron text chat editor inserts the expression + screenshot DLL at the cursor

Set div editable Contenteditable =”true” custom bidirectional binding V-model, insert dynamic emoticons at cursor position.

Since it has been shared before, I will not introduce it here

Juejin. Cn/post / 684490…

Finally, share an instance of Uniapp

Based on vue + uniapp live project | uni – app imitation trill/Momo studio