上一期咱们介绍了如何设置伪协定,并通过伪协定链接拉起客户端,其实伪协定还有很多场景的,比方百度网盘或者迅雷,点击网页上的链接进行下载,或者点击链接拉起客户端后关上某个页面,其实这都是能够用伪协定链接实现的,链接中的参数就和网页的参数没啥区别,本期就介绍如何获取伪协定链接中的参数。
实现目标
- 软件敞开时通过伪协定拉起软件获取该伪协定链接。
- 软件启动时通过伪协定拉起软件获取该伪协定链接。
- 通过伪协定传入一个图片链接和router path门路,跳转该门路,并下载图片本地加载显示。
伪协定获取差别
上一章咱们介绍了伪协定是怎么启动客户端的,即:
- Windows是通过注册表写入伪协定,调用利用启动exe和
%1
启动客户端的。 - Mac是通过软件包中的
info.plist
文件设置启动客户端的。
这两者的启动形式不同,故获取形式也是不同的,咱们来看一下通过伪协定的启动流程吧:
Windows伪协定启解决
- 首先软件处于敞开状态的话,咱们在浏览器上关上伪协定链接,会注册表下来找对应的伪协定,启动exe并传入伪协定链接(
%1
),也就是咱们实际上关上的是xxx.exe vue-cli-electron://xxxx
,
此时能够间接通过process.argv
来获取这个伪协定链接,之前说了process.argv
这个是数组,外面是Electron的启动参数,如果咱们是通过伪协定拉起软件的话,数组最初一项就是咱们的伪协定链接
process.argv:[ xxx.exe, ....., vue-cli-electron://xxxx]
那么此时伪协定为process.argv[process.argv.length - 1]
- 软件处于开启状态的话,咱们能够通过app的
second-instance
事件来获取这个argv,second-instance
当第二个实例被执行并且调用app.requestSingleInstanceLock()
时触发的,解释一下就是咱们的软件正在运行,伪协定触发关上exe,咱们主过程中调用了app.requestSingleInstanceLock()
的话,second-instance
就会触发,直观体现为伪协定关上软件,触发second-instance
事件,咱们能够在这个外面拿到argv。
import { app } from 'electron'import global from '../config/global'const gotTheLock = app.requestSingleInstanceLock()export default function() { // 点击图标启动时检测窗口是否存在,存在则关上 if (!gotTheLock) { app.quit() } else { app.on('second-instance', (event, argv) => { console.log(argv[argv.length - 1]) const win = global.sharedObject.win if (win) { if (win.isMinimized()) win.restore() if (win.isVisible()) { win.focus() } else { win.show() win.setSkipTaskbar(false) } } }) }}
Mac伪协定解决
Mac软件的启动就没啥参数可带的了,所以process.argv
这个货色没啥用,那么如何获取呢,看看官网形容链接:
在 macOS 上, 当用户尝试在 Finder 中关上您的应用程序的第二个实例时, 零碎会通过收回 open-file 和 open-url 事件来主动强制执行单个实例,。 然而当用户在命令行中启动应用程序时, 零碎的单实例机制将被绕过, 您必须手动调用此办法来确保单实例。
故咱们能够通过open-url
来获取咱们的伪协定链接,注:Mac零碎无论软件启动或没启动都是通过open-url
来拿取的
app.on('open-url', (_event, urlStr) => { console.log(urlStr)})
具体实现
winSingle
import { app } from 'electron'import global from '../config/global'const gotTheLock = app.requestSingleInstanceLock()export default function() { // 点击图标启动时检测窗口是否存在,存在则关上 if (!gotTheLock) { app.quit() } else { // 这里是软件在启动时,伪协定关上触发的 app.on('second-instance', (event, argv) => { console.log(argv) const win = global.sharedObject.win // 间接把伪协定链接发送给渲染过程 win.webContents.send('renderer-scheme', argv[argv.length - 1]) if (win) { if (win.isMinimized()) win.restore() if (win.isVisible()) { win.focus() } else { win.show() win.setSkipTaskbar(false) } } }) }}
主过程
import winSingle from './services/winSingle'winSingle()app.isReady() ? onAppReady() : app.on('ready', onAppReady)async function onAppReady() { if (!process.env.WEBPACK_DEV_SERVER_URL) { createProtocol('app') } // 这里怎么解决看集体爱好,你能够启动时就依据scheme关上对应的窗口,或者是在窗口加载实现后发个告诉给渲染过程,渲染过程进行重定向。 // if (process.argv.length > (app.isPackaged ? 1 : 2)) { // const scheme = process.argv[process.argv.length - 1] // 解决scheme省略 // initWindow('#xxxpath') // } else { // initWindow('') // } initWindow('') // 这里的逻辑是win敞开通过伪协定拉起软件,因为咱们要告诉渲染过程,所以得在渲染过程加载结束后告诉 win.webContents.once('did-finish-load', () => { // 间接关上软件的话开发环境的启动参数为2,安装包为1,大于这个数的话阐明是通过伪协定拉起软件的 if (process.argv.length > (app.isPackaged ? 1 : 2)) { // 咱们这里被动触发'second-instance',传入process.argv,在那边对立解决了 app.emit('second-instance', null, process.argv) } })}// mac伪协定链接就是urlStrapp.on('open-url', (_event, urlStr) => { console.log(urlStr) if (win) { // 这里是mac软件关上时应用伪协定关上软件 win.webContents.send('renderer-scheme', urlStr) if (win.isMinimized()) win.restore() if (win.isVisible()) { win.focus() } else { win.show() win.setSkipTaskbar(false) } } else { // 这里是mac软件敞开时应用伪协定关上软件,如果你两头process.argv没有扭转能够这样写,会持续走下面win的did-finish-load的流程 // 如果有扭转的话老老实实写个did-finish-load进行win.webContents.send('renderer-scheme', urlStr)推送 process.argv.push(urlStr) }})
我这里是主过程获取到伪协定链接,而后发告诉给渲染过程的,一些不懂的中央请看下面正文解释,简略说一下就是:
- 在
open-url
里解决Mac的伪协定,依据win的值来辨别软件是处于开启还是敞开。 - 在
ready
里拿到伪协定的是软件处于敞开状态的,second-instance
里软件是启动状态。 - Mac软件敞开状态启动的话,argv里只有启动门路一项,不会走argv.length > 1这边的逻辑的,然而open-url会比ready先触发,咱们能够在这个外面进行手动argv.push(伪协定链接)让其走Win软件敞开启动的逻辑。
渲染过程解决
这里咱们应用的伪协定链接为vue-cli-electron:///file/localFile?image=https://xuxinblog.oss-cn-qingdao.aliyuncs.com/blog/2021/07/01/1.jpg
,拿到的也是这个残缺链接,咱们解决一下这个链接,跳转到/file/localFile
,并下载query参数外面的image图片地址。下载及显示逻辑用之前的加载本地文件的逻辑。
App.vue
onMounted(() => { window.ipcRenderer.on('renderer-scheme', (_event, data) => { console.log(data) const urlObj = new URL(data) const query = {} urlObj.search.slice(1).split('&').forEach(s => { const item = s.split('=') query[item[0]] = item[1] }) router.replace({ path: urlObj.pathname.slice(2), query }) })})onUnmounted(() => { window.ipcRenderer.removeAllListeners('renderer-scheme')})
localFile.vue
onMounted(() => { const localImage = LgetItem('localImage') if (route.query.image) { download(route.query.image) } else { if (localImage) { state.image = localImage } }})
好了,接下来应用浏览器关上vue-cli-electron:///file/localFile?image=https://xuxinblog.oss-cn-qingdao.aliyuncs.com/blog/2021/07/01/1.jpg
试试,看看拉起软件后是否跳转到本地文件的路由,且显示的是伪协定中image的图片。
本系列更新只有利用周末和下班时间整顿,比拟多的内容的话更新会比较慢,心愿能对你有所帮忙,请多多star或点赞珍藏反对一下
本文地址:https://xuxin123.com/electron/url-scheme-query
本文github地址:链接