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

news2024/11/16 17:42:20

系列文章目录

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


文章目录

  • 系列文章目录
  • 前言
  • 一、我们如何思考
  • 二、解决问题
    • 1.选择方案
    • 2. 发现electron多开窗口监听
    • 3.查找可使用的官方参数
    • 4.示例代码
  • 总结


前言

从本系列第六篇文章开始,我们一共用三篇文章讲解了系统级右键实现文件上传、手动修改注册表实现级联菜单、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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/509754.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker 安全及日志管理

Docker 安全及日志管理 Docker 容器与虚拟机的区别隔离与共享性能与损耗 Docker 存在的安全问题Docker 自身漏洞Docker 源码问题Docker 架构缺陷与安全机制Docker 安全基线标准 容器相关的常用安全配置方法容器最小化Docker 远程 API 访问控制重启 Docker在宿主机的 firewalld …

ASEMI代理ADI亚德诺ADXL345BCCZ-RL7车规级芯片

编辑-Z ADXL345BCCZ-RL7特点&#xff1a; 超低功率&#xff1a;在测量模式下低至23A 在VS2.5 V的待机模式下为0.1A&#xff08;典型&#xff09; 功耗会随带宽自动调整 用户可选分辨率 固定的10位分辨率 全分辨率&#xff0c;其中分辨率随着g范围的增加而增加&#xff0…

00后才是内卷之王,被卷的头皮发麻....

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。这不&#xff0c;前段时间我们公司来了个00年的&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。…

Redis主从复制(搭建集群的一种方式)【故障转移,内存,回收】

做一个伪集群 配置文件&#xff1a; daemonize yes port 7777 logfile .redis-7777.log dir ./ bind 0.0.0.0启动6666 and 7777 现在设置主从表 但是有个问题我把服务器停掉 关系就会解除 还可以手动解除 slaveof no one 命令 配置Sentinel&#xff08;哨兵&#…

基于络达SOC AB1562A TWS蓝牙耳机设计

V hezkz17进数字音频答疑 一 原理框图 二 电子电路设计 (1)SOC主芯片 (2) 最小系统晶振电路设计26MHZ (3) 电池电路设计 4 充电电路与充电保护设计 5 LED输出电路设计</

hexo stellar设置目录跳转记录

1. 使用hexo-toc插件 一开始使用的是hexo-toc的插件&#xff1a;参考hexo安装toc插件 详细的可以看github的项目&#xff1a; github-hexo-toc 更加详细的配置&#xff1a; Hexo添加Toc支持&#xff0c;生成文章目录 2. 官网的方式&#xff08;推荐&#xff09; stellar博…

flink cdc原理与使用

flink cdc原理与使用 1 cdc 介绍1.1 cdc简介与对比1.2 基于日志的 CDC 方案介绍 2 基于 Flink SQL CDC 的数据同步方案实践2.1 案例 1 : Flink SQL CDC JDBC Connector2.2 案例 2 : CDC Streaming ETL2.3 案例 3 : Streaming Changes to Kafka 3 Flink SQL CDC 的更多应用场景…

Java EE企业级应用开发(SSM)第10章

第10章MyBatis核心配置及动态SQL 一.预习笔记 1.第九章的细节处理 1-1.mappers标签中的配置 1-2.jdbc属性文件的配置 1-3.包的别名配置 2.Mybatis核心配置文件 2-1&#xff1a;settings标签&#xff08;P145-146中的表10-1&#xff09; 2-2.类型别名 3.Mybatis映射文件 3-1…

项目集管理绩效领域

项目集管理绩效领域是对活动或职能相关领域的补充分组&#xff0c;这些活动或职能在项目集管理工作的 整个范围内&#xff0c;专门描述和区分一个绩效领域中的活动。 本章包括&#xff1a; 项目集管理绩效领域的定义项目集管理绩效领域的交互组织战略、项目组合管理和项目集管…

vue 水印组件

效果图展示 Watermark 参数说明类型默认值版本width水印的宽度&#xff0c;content 的默认值为自身的宽度number120height水印的高度&#xff0c;content 的默认值为自身的高度number64rotate水印绘制时&#xff0c;旋转的角度&#xff0c;单位 number-22zIndex追加的水印元素…

24.eslint

eslint是约束代码写法的插件&#xff0c;比如组件的命名必须要用驼峰命名这种 eslint官网 检测并修复 JavaScript 代码中的问题。 - ESLint - 插件化的 JavaScript 代码检查工具 目录 1 vue-cli的eslint 2 标准规则 2.1 不能连续出现两个空行 2.2 结尾必须有空行 2.3…

深入了解Dubbo SPI 工作机制——@Activate (5)

在上一篇Dubbo 基于xml文件分析主流程源码 &#xff08;4&#xff09;_chen_yao_kerr的博客-CSDN博客中, 我们已经初步了解了Dubbo SPI的 key - value 结构。接下来将会继续分享Dubbo SPI其他功能的使用方式&#xff0c;并且从源码的角度去一谈究竟。 Activate注解 参数名 …

【数据结构】链表OJ:力扣141.环形链表、142.环形链表II

今天要分享的关于链表的题目是环形链表 目录 题目141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 题解 关于快慢指针的深入研究 题目2&#xff1a;142. 环形链表 II - 力扣&#xff08;LeetCode&#xff09; 题解 以下是题目链接 141. 环形链表 - 力扣&#xff…

塑料回收---未来化工行业的新兴增长领域

大量的旧塑料被浪费 从南极洲到北极&#xff0c;在原始海岸线上冲刷的塑料废物&#xff0c;以及太平洋上巨大的塑料废物浮岛&#xff0c;得到了媒体的广泛报道&#xff0c;并促成了消费者消费意识发生转变。 研究表明&#xff0c;大多数废旧塑料被送往垃圾填埋场和焚烧&#…

Go语言设计模式之责任链模式

其实很多人不知道,责任链模式是我们工作中经常遇到的模式,特别是web后端工程师,我们工作中每时每刻都在用:因为市面上大部分的web框架的过滤器基本都是基于这个设计模式为基本模式搭建的。 1.模式介绍 我们先来看一下责任链模式(Chain Of Responsibility Design Pattern…

react实现点击获取json对象的jsonPath

准备 安装 react-json-view&#xff1a;npm install --save react-json-view 可参考的一些开源库&#xff1a;react-json-path-picker&#xff0c;json-path-picker 线上工具&#xff1a;jsonpath tool JsonPath JsonPath官方文档 用来解析多层嵌套的json数据。JsonPath 是一…

8分钟的面试,我直呼太变态了......

干了两年外包&#xff0c;本来想出来正儿八经找个互联网公司上班&#xff0c;没想到算法死在另一家厂子。 自从加入这家外包公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到11月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资…

08 FPGA—计数器与分频器的应用

1. 理论 时序逻辑电路中最基本的单元—寄存器&#xff0c;我们可以使用寄存器来做计数器。基本上关于时间的设计都离不开计数器。 计数器在数字系统中主要是对脉冲的个数进行计数&#xff0c;以实现测量、计数和控制的功能&#xff0c;同时兼有分频功能。计数器一般都是从 0 开…

JSON-框架的具体使用

JSON-框架的具体使用 非 SpringBoot 项目 Jackson Jackson 是另一个流行的JSON序列化和反序列化库&#xff0c;具有以下特点 速度快&#xff1a;Jackson 采用了高效的JSON解析算法和字节码生成技术&#xff0c;使得其序列化和反序列化速度非常快。支持全类型序列化&#xff1…

V8 过去版本的性能提升汇总

&#xff08;预测未来最好的方法就是把它创造出来——尼葛洛庞帝&#xff09; V8 官方链接 NodeJs8.3之前的代码优化建议 NodeJs8.3版本之后的turbofan虚拟机引擎 编写性能更高的JavaScript代码 chromium 优化博客 chrom v8版本发布路线图 V8 是 Google 的开源高性能 JavaScri…