关于前端:Electron伪协议参数获取

29次阅读

共计 4608 个字符,预计需要花费 12 分钟才能阅读完成。

上一期咱们介绍了如何设置伪协定,并通过伪协定链接拉起客户端,其实伪协定还有很多场景的,比方百度网盘或者迅雷,点击网页上的链接进行下载,或者点击链接拉起客户端后关上某个页面,其实这都是能够用伪协定链接实现的,链接中的参数就和网页的参数没啥区别,本期就介绍如何获取伪协定链接中的参数。

实现目标

  1. 软件敞开时通过伪协定拉起软件获取该伪协定链接。
  2. 软件启动时通过伪协定拉起软件获取该伪协定链接。
  3. 通过伪协定传入一个图片链接和 router path 门路,跳转该门路,并下载图片本地加载显示。

伪协定获取差别

上一章咱们介绍了伪协定是怎么启动客户端的,即:

  1. Windows 是通过注册表写入伪协定,调用利用启动 exe 和 %1 启动客户端的。
  2. Mac 是通过软件包中的 info.plist 文件设置启动客户端的。

这两者的启动形式不同,故获取形式也是不同的,咱们来看一下通过伪协定的启动流程吧:

Windows 伪协定启解决

  1. 首先软件处于敞开状态的话,咱们在浏览器上关上伪协定链接,会注册表下来找对应的伪协定,启动 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]

  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 伪协定链接就是 urlStr
app.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 地址:链接

正文完
 0