文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue+electron实现创建多窗口及窗口间的通信(实施方案)

2024-04-02 19:55

关注

一、前言

对于一个桌面应用来说,有时候单独一个窗口用户使用起来会不太方便,比方说写日报或者查看文件等,若是在同一窗口内,我只能做一件事,不能边预览文件,边去查看聊天消息内容等。又或者是多个应用间相互关联的需要同步查看的事件,这都是极其不方便的。因此我们可以将某些集成到electron软件中的应用或者某些界面用单独的窗口打开(以下称为独立窗口)。

二、实施方案

1.创建多窗口

首先我们从electron官网中找到创建窗口的方法,electron官网的BrowserWindow,接下来我们就简单写一个独立窗口的创建。这个窗口可以打开外部应用也可以是应用内部。

// windows/CreateIndependentWindow.js
import { BrowserWindow, globalShortcut, ipcMain } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
// 关于这个插件,可以看下前几天我写的解决electron白屏那篇文章
import CreateProcessLoadingPage from './CreateProcessLoadingPage'

const CreateIndependentWindow = ({
  ...data
}, win) => {
  const obj = {
    // 窗口的大小可以通过传进来的参数控制
    height: data.height || 640,
    width: data.width || 1024,
    show: false, // 初始是否可显示
    center: true,
    // 窗口是否可以进入全屏状态
    fullscreenable: false, 
    closable: true, // 窗口是否可关闭
    resizable: true, // 禁止改变主窗口尺寸
    webPreferences: {
      nodeIntegration: true, // 启用Node integration
      webSecurity: false,
      webviewTag: true, // 允许在页面内使用webview标签
      enableRemoteModule: true, // 允许渲染进程使用remote模块
      nodeIntegrationInWorker: true, // 在Web工作器中启用了Node集成
      // 允许在子页面(iframe)或子窗口(child window)中集成Node.js
      nodeIntegrationInSubFrames: true 
    }
  }
  // 这里创建窗口实例
  const independentWindow = new BrowserWindow(obj)
  // 注册全局快捷键-打开开发者工具(方便查看问题)
  globalShortcut.register('CommandOrControl+alt+shift+l', () => {
    independentWindow.webContents.openDevTools()
  })
  // 设置窗口名称
  independentWindow.setTitle(data.windowTitle || '人脉旺')
  // 这里将当前窗口的唯一id,存入全局变量,以容易区分多个独立窗口
  // 变量声明下方说明
  global.sharedObject.independentWindow.set(data.windowTitle, independentWindow.webContents.id)
  // 声明打开页面的url
  let winURL = ''
  // /IndependentWindow这个路由是在渲染进程创建的承载外部链接的独立窗口的页面
  if (process.env.WEBPACK_DEV_SERVER_URL) { // 判断若为开发环境
    // independentWindow.webContents.openDevTools()
    winURL = process.env.WEBPACK_DEV_SERVER_URL + '#/' + (data.inUrl ? data.inUrl : 'IndependentWindow')
  } else {
    createProtocol('app')
    winURL = 'app://./index.html#' + (data.inUrl ? data.inUrl : '#/IndependentWindow')
  }
  // 这里是为了获取拼接需要传入到页面的参数
  const param = Object.keys(data).reduce((pre, cue) => {
    return data[cue] ? `${pre}${pre === '?' ? '' : '&'}${cue}=${data[cue]}` : pre
  }, '?')
  // 使用loadURL方法将页面注入到窗口
  independentWindow.loadURL(winURL + param)
  // 若参数设置开启最大化窗口
  if (data.maxSize) {
    independentWindow.maximize()
  }
  // 加载页面loading
  CreateProcessLoadingPage(independentWindow, data)

  independentWindow.on('close', (e) => {
    globalShortcut.unregister('CommandOrControl+alt+shift+l')
    global.sharedObject.independentWindow.delete(data.windowTitle)
    setTimeout(() => {
      if (!independentWindow.isDestroyed() && independentWindow) {
        independentWindow.destroy()
      }
    }, 100)
  })

  global['independentWindow-' + independentWindow.webContents.id] = independentWindow
}
export default CreateIndependentWindow

之后我们在主进程中做一个监听,用来创建独立窗口

ipcMain.on('createOtherWindow', (e, data) => { // type窗口类型,data 参数
    const name = data.windowTitle
    // 判断当前窗口是否已经存在, 存在的话 直接唤起
    if (global.sharedObject.independentWindow.has(name)) {
        const id = global.sharedObject.independentWindow.get(name)
        global['independentWindow-' + id].show()
    } else {
        CreateIndependentWindow(data, win)
    }
})

这里我们记得声明一下存储独立窗口id的变量

// background.js
// 多窗口数据存储
global.sharedObject = {
   independentWindow: new Map(),
}

之后我们在渲染进程创建一个页面,用来展示外部链接页面

<template>
  <div class="independent-window">
    <webview id="myWebView" :src="outUrl" style="display:inline-flex; width:100%; height:100%" allowpopups></webview>
  </div>
</template>

<script>
export default {
  name: 'IndependentWindow',
  data () {
    return {
      outUrl: '',
    }
  },
  created () {
    this.outUrl = this.$route.query.outUrl
  },
  mounted () {
    this.eventHandler()
  },
  methods: {
    // 监听打开webview控制台的快捷键
    eventHandler () {
      const webview = document.querySelector('#myWebView')
      // 用于查看webview内第三方应用问题,快捷键打开webview的开发者工具
      window.addEventListener('keydown', e => {
        if (e.altKey && e.ctrlKey && e.shiftKey && e.keyCode === 190) {
          webview.openDevTools()
        }
      })
    }
  }
}
</script>
<style lang="less" scoped>
.independent-window {
  width: 100%;
  height: 100%;
}
</style>

综上,我们就创建了一个独立窗口,这个独立窗口可以打开项目内页面又或者第三方外部链接窗口。

2.多窗口间的通信

electron官方文档给我们提供了关于多个窗口间通讯的方法, 对于多窗口间的通讯,多是指渲染进程间的通讯。 这里我们可以使用ipcRenderer.sendTo()这个方法,来进行多窗口建的通信。详见官方文档说明

ipcRenderer.sendTo(webContentsId, channel, ...args)​ 以下是官方文档内容

通过 channel 发送消息到带有 webContentsId 的窗口.

这里就用到了我们之前在global.sharedObject.independentWindow中存储的各个窗口的id。 划重点一定是窗口实例的webContentsId的id,而不是窗口的id,别问我怎么知道的,问也不说???。

// 窗口1中
const remote = window.require('electron').remote
// 通过窗口名获取窗口id
const id = remote.getGlobal('sharedObject').independentWindow.get('窗口名windowTitle')
ipcRenderer.sendTo(id, '约定的通信协议', 参数)

// ===========================-.-===========

// 在另一个窗口中
ipcRenderer.on('约定的通信协议', (e, url) => {
  //做你想做的
})

这样我们就实现多窗口渲染进程间的通讯。

三、后记

多窗口的场景有人多,有时候情况可能会很复杂,我建议可以将那些特殊作用的窗口,单独创建一个,而不是都放到通用的独立窗口中,这样管理起来会很方便。

到此这篇关于vue+electron实现创建多窗口及窗口间的通信的文章就介绍到这了,更多相关vue electron多窗口内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯