vue3+electron开发桌面软件(9)——选中多个文件,右键上传

系列文章目录

系列第一篇: vue3+electron开发桌面软件入门与实战(0)——创建electron应用



前言

从本系列第六篇文章开始,我们一共用三篇文章讲解了系统级右键实现文件上传、手动修改注册表实现级联菜单、electron操作修改注册表实现级联菜单。

网络上大部分文章也止步于此,但是在很多业务场景下,我们都需要右键选中多个文件,实现一键上传功能。如图:

在这里插入图片描述

网上部分文章也提到了多选文件(图片)并上传,但是基本都未进行任何代码操作,而是使用鼠标拖动多个文件放到electron应用的图标,利用electron默认的能力实现多文件上传,针对我们具体的需求,这种方式只能算是一种无法解决问题时的妥协方案。


一、我们如何思考

遇到问题我们应该如何思考呢?

通过查阅网络资料,我们可以大胆设想,可能有以下两种方案:

  1. 我们依赖注册表参数“1%”获取文件路径,发现这个参数只能传递一个文件路径。那么有没有一个类似的参数,或者通过某种参数操作,可以获取多个文件路径?
  2. 通过查阅资料,发现有大佬通过cmd命令行传参时,可以控制黑窗口的显示,当出现第二个窗口时,不显示,并把获得的参数传递给第一个窗口,我们能不能借鉴这种方式,把多个文件路径都汇集到第一个应用窗口?

二、解决问题

1.选择方案

老规矩,如果着急借鉴代码实现效果,可以不用看我bb解决问题的方式。直接跳转到最后。

最初我是倾向于借助注册表参数解决问题的,所以研究了很多注册表相关知识,发现以我目前水平,这条路走不通。

所以最终确定为选择第二种方案,后续文件打开的应用窗口将参数传递给第一个窗口。

2. 发现electron多开窗口监听

借鉴网上大佬cmd多窗口时传参的思路,我们如果想要实现electron多窗口传参,就需要在electron打开新窗口的时候,拿到参数,传递给第一个打开的活跃窗口。

这个方案是很麻烦的,全局参数、进程通信(不是electron的进程概念,而是windows进程)、参数管理……想想都头大,所以我开了个头,就放弃继续深入了。因为这时候,我发现这个场景似曾相识。

没错,就是我最开始写这个项目的时候,为了防止多开窗口,在electron的main.js写过一个监听:

    app.on('second-instance', (event, commandLine, workingDirectory, additionalData) => {
            // 有人试图运行第二个实例,我们应该关注我们的窗口
            if (win) {
                if (win.isMinimized()) win.restore()
                win.focus()
            }
        })

这个监听就是在做windows层面的进程管理(如果不理解,可以略过这句话,直接看后面的大白话。)

说白了,这个监听就是当我们打开第二个窗口的时候,electron可以监听到,然后我们在里面做了个判断,如果win窗口存在,那么就不要打开窗口了,而是显示我们存在的窗口。

这不就是electron官方提供的多开窗口监听吗,用官方的,省事不说,起码不会有太多bug吧。

如果我们去掉这段监听代码,就会发现如果多选文件后打开应用,那么我们选择了几个文件,就会打开几个应用,并且每个应用都能打印出对应文件的地址。即应用拿到了各自文件的地址。

所以我们现在要做的,就是怎么把后续打开应用中的文件地址,都传递给第一个应用窗口。

3.查找可使用的官方参数

我们为什么要使用大企业背书的框架?就是因为我们相信他们是在做产品,而不是仅仅做个项目。产品,就要考虑更多场景,所以我觉得官方既然想到了多窗口管理,就不会不考虑多窗口参数间的通讯。

果然,经过查阅得知additionalData传递的就是后续打开窗口的参数。代码如下:

        app.on('second-instance', (event, commandLine, workingDirectory, additionalData) => {
            // 输出从第二个实例中接收到的数据,传入到fileController中
            const url=argvController.getConfigByArgv('getUrl',additionalData.argv)
            fileController.addFileUrl(url)
            // 有人试图运行第二个实例,我们应该关注我们的窗口
            if (win) {
                if (win.isMinimized()) win.restore()
                win.focus()
            }
        })

不用关心getConfigByArgv方法和fileController.addFileUrl,这只是我封装的方法,如何去操作拿到的文件地址。

这一部分真正核心的代码就是一个参数:additionalData.argv。这里面放着后面窗口的argv参数。而通过本系列前面单文件上传的文章可以知道,argv中保存着文件的地址。

我们拿到所有文件地址后,就可以随意操作多选的文件了。

4.示例代码

  1. main.js中监听多文件打开的窗口参数
        app.on('second-instance', (event, commandLine, workingDirectory, additionalData) => {
            // 输出从第二个实例中接收到的数据,传入到fileController中
            const url=argvController.getConfigByArgv('getUrl',additionalData.argv)
            fileController.addFileUrl(url)
            // 有人试图运行第二个实例,我们应该关注我们的窗口
            if (win) {
                if (win.isMinimized()) win.restore()
                win.focus()
            }
        })
  1. getConfigByArgv是我用来解析argv参数的方法,这里为了拓展性写了个策略模式,如果不好接受,不用有心智负担,只需要按照自己喜欢的方式,从argv中拿到文件地址就可。
const argvTypes={
    //为获取参数设计策略模式
    getUrl(argv){
        //获取地址
        for (let i = 0; i < argv.length; i++) {
            if (argv[i].includes('upload-tome') ) {
                return argv[i + 1]
                break
            }else if(argv[i].includes('upload-toother')){
                return argv[i + 1]
                break
            }else if(argv[i].includes('upload-backgorundget')){
                return argv[i + 1]
                break
            }
        }
    },
    getTomeType(argv){
        //获取tome后面附带的参数值
        for (let i = 0; i < argv.length; i++) {
            if (argv[i].includes('upload-tome') ) {
                return argv[i]
                break
            }
        }
    },
    getCmdType(argv){
        //获取tome、toother两个参数
        let flag='get'
        // console.log(config)
        for (let i = 0; i < argv.length; i++) {
            // debugger
            if (argv[i].includes('upload-tome') ) {
                flag=config.toTypeList.tome
                break
            }else if(argv[i].includes('upload-toother')){
                flag=config.toTypeList.toother
                // flag='tome'
            }else if(argv[i].includes('upload-get')){
                flag=config.toTypeList.get
            }else if(argv[i].includes('upload-backgorundget')){
                flag=config.toTypeList.get
            }
        }
        return flag
    }
}
const getConfigByArgv=(type,argv)=>{
    return argvTypes[type](argv)
}
  1. addFileUrl方法就比较简单了,就是为了得到一个文件数组:
let fileUrlArr = []
//省略无关代码...
const addFileUrl = (v) => {
    fileUrlArr.push(v)
}
  1. 组合最终的files:
    const progressArgv = progress.argv
    const cwd = progress.cwd()
    let url = argvController.getConfigByArgv('getUrl',progressArgv)  //获取第一实例的文件地址
    let files = []
    files.push(url, ...fileUrlArr)

大家对上面的代码应该不陌生,是系列前面文章里获取文件地址的一段代码,现在我们得到了第二个窗口后的文件数组fileUrlArr,只需要和第一个窗口的文件地址合并为新的数组files,就可得到最终结果。

结合文章开头的图,点击上传后,在文件列表显示已上传的文件详情:

在这里插入图片描述
在这里插入图片描述


总结

至此,关于文件上传的基本功能都已完成,后续可能还会有一些样式的优化,比如正常打开时,应用在屏幕中央,通过文件右键打开时,应用在右下角有一些特殊样式。

用最简单的方式,完成产品的需求,才是一个技术人该有的追求。千万不要成为企业里那个一整天都在反复修改代码、反复解决问题的人。短期看,项目离不开你,长期看,你只能干到35。

能看到这的应该都是对electron比较感兴趣的同学,我最近在参加csdn新星计划导师活动,我对活动细节不了解也不太关心,不过有兴趣的同学可以免费报名,有集中讨论讲解的环节,应该比私信要效率更高。

活动地址请戳:https://bbs.csdn.net/topics/615149275

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
首先,VueElectron是两个不同的技术,Vue是一种用于构建用户界面的JavaScript框架,而Electron是一种用于构建跨平台桌面应用程序的框架,它使用Web技术(HTML,CSS和JavaScript)来构建应用程序。 如果你是0基础入门,首先需要学习VueElectron的基础知识。以下是一些学习资源: Vue: - Vue官方文档:https://v3.vuejs.org/guide/introduction.html - Vue Mastery:https://www.vuemastery.com/ - Codecademy:https://www.codecademy.com/learn/learn-vue Electron: - Electron官方文档:https://www.electronjs.org/docs - Udemy:https://www.udemy.com/course/electron-from-scratch/ - Pluralsight:https://www.pluralsight.com/courses/electron-fundamentals 一旦你学习了VueElectron的基础知识,你可以开始构建你的第一个Vue3+Electron桌面应用程序。以下是一些步骤: 1. 安装Vue CLI和Electron:使用npm安装Vue CLI和Electron。 ``` npm install -g @vue/cli npm install -g electron ``` 2. 创建Vue项目:使用Vue CLI创建一个新的Vue项目。 ``` vue create my-electron-app ``` 3. 添加Electron支持:在Vue项目中安装electron-builder。 ``` cd my-electron-app vue add electron-builder ``` 4. 编写代码:你现在可以开始编写VueElectron代码了。你可以在Vue组件中使用Electron API来访问系统资源。你可以在Electron主进程中编写Node.js代码以访问底层系统资源。 以上是一个简单的介绍,希望对你有所帮助。祝你好运!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中二少年学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值