V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaoyan2017
V2EX  ›  推广

基于 electron+vue 仿微信客户端聊天|electron-vue 聊天室

  •  
  •   xiaoyan2017 · 2020-01-10 09:09:12 +08:00 · 3982 次点击
    这是一个创建于 1765 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目简介

    electron-vchat 项目是基于 electron+Vue.js+electron-vue+Vuex+Node+webpack+wcPop 等技术实现仿制微信桌面聊天室,实现了消息发送 /表情,图片 /视频预览,拖拽上传 /粘贴截图发送 /微信 dll 截图,右键菜单、朋友圈 /红包 /换肤等功能

    技术架构:

    • 框架技术:electron + electron-vue + vue
    • 状态管理:Vuex
    • 地址路由:Vue-router
    • 字体图标:阿里 iconfont 字体图标库
    • 弹窗插件:wcPop
    • 打包工具:electron-builder
    • 图片组件:vue-photo-preview
    • 视频组件:vue-video-player
    /**
     * @Desc   公共及全局组件配置
     * @about  Q:282310962  wx:xy190310
     */
    
    // 引入公共组件
    import winBar from './components/winbar'
    import sideBar from './components/sidebar'
    
    // 引入公共样式
    import './assets/fonts/iconfont.css'
    import './assets/css/reset.css'
    import './assets/css/layout.css'
    
    // 引入弹窗 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 => {
        // 注册组件
        Vue.component('win-bar', winBar)
        Vue.component('side-bar', sideBar)
    
        // 应用实例
        Vue.use(photoView, {
            // loop: false, //循环
            // fullscreenEl: true, //全屏
            // arrowEl: true, //左右按钮
        })
        Vue.use(videoPlayer)
    }
    
    export default install
    

    Electron 是由 Github 开发,用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库。

    https://electronjs.org/

    https://electron.org.cn/vue/index.html

    https://github.com/SimulatedGREG/electron-vue

    electron 主进程创建窗体

    通过 electron 里的 BrowserWindow 对象创建和控制浏览器窗口

    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(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
      }
    }
    

    electron 自定义最大 /小化、关闭按钮、无外框窗口

    electron 中配置 frame: false 后,就能去除原窗体顶部

    设置 css -webkit-app-region: drag; 就能实现局部拖动效果

    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()
            }
        }
    }
    

    ** 注意:默认设置-webkit-app-region: drag 后,下面的元素不能点击操作,可通过设置需点击元素 no-drag 即可。**

    electron 实现编辑器插入表情+截图功能

    vue electron 中设置 div 可编辑 contenteditable="true" 自定义双向绑定 v-model

    electron-vue 仿微信聊天编辑器|表情|截图功能分享

    好了,运用 electron 开发客户端聊天项目就介绍到这里,后续继续分享实例项目。

    最后附上:taro+react 多端聊天室|taro 仿微信界面

    作者:xiaoyan2017
    链接: https://juejin.im/post/5e141ffc5188253a57049a63
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    9 条回复    2020-01-10 13:09:46 +08:00
    looseChen
        1
    looseChen  
       2020-01-10 09:16:16 +08:00
    请选择正确的节点谢谢。
    yaoseu1717
        2
    yaoseu1717  
       2020-01-10 09:23:18 +08:00
    性能怎么样
    zhoushiya
        3
    zhoushiya  
       2020-01-10 09:33:53 +08:00
    楼主专注于各种技术实现仿微信。。。
    sevenzhou1218
        4
    sevenzhou1218  
       2020-01-10 09:34:29 +08:00
    有 git 地址嘛?
    7654
        5
    7654  
       2020-01-10 09:37:55 +08:00
    PC 微信终于可以用帐号密码登录了,还可以抢红包[大雾]~
    ryougifujino
        6
    ryougifujino  
       2020-01-10 09:39:18 +08:00
    还以为开源的
    leon0903
        7
    leon0903  
       2020-01-10 09:59:39 +08:00
    nb。
    v2student
        8
    v2student  
       2020-01-10 10:31:23 +08:00
    又是楼主你,广告都打到 v2 来了,就这几个截图和代码,真心看不出有没有 bug
    chanchan
        9
    chanchan  
       2020-01-10 13:09:46 +08:00
    仿微信?能不能学点好的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1210 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 23:57 · PVG 07:57 · LAX 15:57 · JFK 18:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.