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

目录
  • 一、前言
  • 二、实施方案
    • 1.创建多窗口
    • 2.多窗口间的通信
  • 三、后记

一、前言

对于一个桌面应用来说,有时候单独一个窗口用户使用起来会不太方便,比方说写日报或者查看文件等,若是在同一窗口内,我只能做一件事,不能边预览文件,边去查看聊天消息内容等。又或者是多个应用间相互关联的需要同步查看的事件,这都是极其不方便的。因此我们可以将某些集成到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'
/**
 * 必传参数
 * outUrl  外部链接
 * or
 * inUrl 内部链接
 * windowTitle 页面标题 注意:此值不可重复
*/
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) 以下是官方文档内容

  • webContentsId number
  • channel string
  • ...args any[]

通过 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多窗口内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue electron零基础使用教程

    需求:给vue项目加一个外壳(electron),顾名思义也就是使用electron应用程序运行vue项目,直接将写好上线的vue项目在线地址放入electron程序中即可 操作步骤: 1.构建:构建应用程序首先要先安装electron相关依赖包以及搭建框架.在这里就不详细赘述了,直接上官网看文档https://www.electronjs.org/zh/docs/latest/tutorial/quick-start 2.打包:此时就到了重要的时候,官方指定的是使用脚手架打包-----Elec

  • 用electron 打包发布集成vue2.0项目的操作过程

    手里有个老项目是基于element admin框架下的,之前写的时候没考虑到要打包成桌面端,后期需要打包成客户端,然后就开始了一些列版本操作,看着百度了都很简单,把electron 加入到自己项目中各种不兼容,升级版本,改代码各种百度,一个国庆假期就搞了这个事情,为了后面大家少踩点坑,打算详细的写写我的踩坑之路还有版本配置(版本配置真的很有必要,不要嫌麻烦,一步一步走哈) 1.大家比较关注的版本配置表 node.js v15.0.0 electron V14.2.9 vue 2.7.8 sass

  • 关于electron-vue打包后运行白屏的解决方案

    目录 electron-vue打包后运行白屏的解决 electron-vue打包之后只有空白页问题 原因 electron-vue打包后运行白屏的解决 找到.electron-vue文件夹中的webpack.renderer.config.js文件,注释掉下面这段 然后再重新打包,问题解决. electron-vue打包之后只有空白页问题 原因 使用了history路由导致打包之后 只有空白页面,将路由改成hash之后就有显示了 以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们.

  • vue electron实现无边框窗口示例详解

    目录 一.前言 二.实现方案 1.创建无边框窗口 2.创建windows窗口控件组件 三.后记 一.前言 无边框窗口是不带外壳(包括窗口边框.工具栏等),只含有网页内容的窗口.对于一个产品来讲,桌面应用带边框的很少,因为丑(我们的UI觉得--与我无关-.-).因此我们就来展开说下,在做无边框窗口时候需要注意的事项以及我踩过的坑. 二.实现方案 1.创建无边框窗口 要创建无边框窗口,只需在 BrowserWindow的 options 中将 frame 设置为 false: const { Bro

  • vue与electron实现进程间的通信详情

    目录 一.配置内容 1.进程间的通信 第一种方式引入ipcRenderer 第二种方式引入ipcRenderer 2.渲染进程常用配置 3.将ipcMain封装到一个js中统一处理 三.总结 前言: 本文主要介绍electron渲染进程和主进程间的通信,以及在渲染进程和主进程中常用的配置项. 一.配置内容 1.进程间的通信 渲染进程和主进程间的通信主要通过ipcRenderer和ipcMain这两个模块实现的,其中ipcRenderer是在渲染进程中使用,ipcMain在主进程中使用. 其中,渲

  • Vue electron前端开启局域网接口实现流程详细介绍

    目录 一.主要实现原理 二.获取本机局域网IP 三.开启服务器 四.关闭服务器 五.简单演示 六.整体代码 七.展望 一.主要实现原理 electron本身就集成了Nodejs,简直是不要太舒服.直接用最基本的http模块开接口即可,也可以用express,看个人喜好.下面演示的是http模块. 二.获取本机局域网IP 首先要获取本机局域网的IP,这就是接口的IP地址了. // 获取本机的局域网IP function getServerIp() { let interfaces = os.net

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

    目录 一.前言 二.实施方案 1.创建多窗口 2.多窗口间的通信 三.后记 一.前言 对于一个桌面应用来说,有时候单独一个窗口用户使用起来会不太方便,比方说写日报或者查看文件等,若是在同一窗口内,我只能做一件事,不能边预览文件,边去查看聊天消息内容等.又或者是多个应用间相互关联的需要同步查看的事件,这都是极其不方便的.因此我们可以将某些集成到electron软件中的应用或者某些界面用单独的窗口打开(以下称为独立窗口). 二.实施方案 1.创建多窗口 首先我们从electron官网中找到创建窗口的

  • 利用shell创建文本菜单与窗口部件的方法

    前言 创建交互式shell脚本最常用的方法是使用菜单.提供各种选项可以帮助脚本用户了解脚本能做什么,不能做什么;通常菜单脚本会清空显示区域,然后显示可用的选项列表.本文给大家详细介绍了shell创建文本菜单与窗口部件的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 创建文本菜单 创建交互式shell脚本最常用的方法是使用菜单,它提供了各种选项帮助脚本用户了解脚本能做到的和不能做的. shell脚本菜单的核心是case命令,该命令会根据用户在菜单上的选择来执行特定命令.

  • 如何使用visual studio2019创建简单的MFC窗口(使用C++)

    本文介绍了如何使用visual studio2019创建简单的MFC窗口(使用C++) ```cpp 使用visual studio 2019 创建过程请参考Bili的上一篇文章⬇⬇ →!使用visual studio 2019 创建简单的MFC窗口「使用底层的C语言」 #include<windows.h> //底层实现窗口的头文件 //6.处理窗口过程 //CALLBACK 代表_stdcall 参数的传递顺序:从右到左依次入栈,并且函数返回前清空堆栈 LRESULT CALLBACK W

  • Vue项目页面跳转时浏览器窗口上方显示进度条功能

    在vue项目中,为了减少首屏加载的时间,通常会开启路由的懒加载.路由懒加载配合gizp确实能帮助我们大大的加快首屏的加载时间. 然而,路由懒加载会使得我们在第一次打开一个新页面的时候,会有一个加载时间.如果在这个时候我们没有一个提示的话,给人的感觉会是好像我点了页面跳转但是没反应.所以,这个时候我们可以加一个进度条来告知用户. 具体实现,我们使用NProgress这个滚动条效果插件. 1.安装: cnpm install --save nprogress 2.在main.js中引入: impor

  • iOS开发创建frame实现window窗口view视图示例

    目录 UIScreen类 UIView UIWindow 实战演练一下: 取得画面工作区域的大小 一些 UIView 中管理 Subview 常用的方法 UIScreen类 要在屏幕上显示内容首先要创建一个窗口承载内容,要创建一个窗口,需要一个边框(frame),含有边框信息的底层 结构就CGRect. 每个能够在屏幕上显示自己的对象都有一个边框,定义了他的显示区域,不过许多高层的视图类会自动计算这一信息.其他的那些类则在视图初始化时通过一个initWithFrame的初始化方法来设置. 再来认

  • vue + Electron 制作桌面应用的示例代码

    1.vue打包 这里使用vue原生打包命令,对vue项目进行打包 npm run build 2.配置 Electron 使用 Electron 制作桌面应用需要两个配置文件 1.package.json 创建一个package.json文件,将以下代码放入 { "name": "demo", //项目名称 "productName": "demo", "author": "作者", &

  • vue + electron应用文件读写操作

    目录 vue + electron应用文件读写 正常操作流程 vue + electron应用文件读写 在使用electron制作桌面应用时,基本都会需要数据的存储. 如果要制作的应用并不复杂,完全可以将数据存储在本地文件当中,然后应用就可以通过这些文件进行数据的读写. 因为electron的主进程是支持node的,所以可以通过fs文件系统对文件完成读写操作. 正常操作流程 首先先创建一个vue项目, 可以使用vue cli进行创建 通过yarn serve命令测试是否能否运行成功,界面正常出现

随机推荐