需求:通过按钮的点击事件控制另一个输出框/按钮的点击

目录

第一章 接到需求

第二章 了解需求

第三章 解决需求 

第四章 优化代码

第五章 解决问题


第一章 接到需求

  • 最近开发的时候遇到这么一个事,技术经理是个全栈,已经把接口生成了,而且前端页面也写好了一个初稿,操作什么的功能基本上已经布局好了,如下:

经理说需求了:这里有两个按钮,一个是导入文件的,一个是导入机构的,你看看怎么把这按钮功能实现,把excel文件导入进去,后台的接口已经写好了 

第二章 了解需求

  • 然后小编接到需求了,clone下代码,根据路由找到对应的页面代码(注释的部分是小编已经写好的代码):

  •  发现这里就是两个按钮,然后设置了权限一些其他配置。
  • (注意事项:我们很多人有的时候为了语义化一些特别容易出现一个问题:就是会用到关键字,比如小编一开始看这个代码的时候,上面写的是@click="import(scope.row.id)",好家伙,不细看不知道,代码一跑吓一跳,直接控制台报错,一定要留意,import是关键字,我们不要直接定义!!!语义化命名不要命名到关键字!!!
  • 好了,接下来进入正题:当我们拿到这么一个需求,首先我们分析一下,很明显,我们拿到的需求是一个上传文件的功能实现,平常我们上传文件很多时候会用到element、antd等等一些框架类的东西来实现这么一个功能。那么问题来了,我们这里就只有按钮,样式、布局都确定了,而且不管我们怎么点击,都没反应。那么接下来我们考虑的是不是给按钮添加点击事件 -> 调出本地文件管理器 -> 点击我们需要上传的文件 -> 上传成功拿到文件的二进制流 -> 准备上传的参数 -> 像后端发送请求 -> 后端返回成功/失败的数据 -> 前端拿到数据进行处理,那么难点在哪呢:一个按钮,怎么能调出本地的文件管理器呢,又怎么知道我们点击文件上传了呢,对于用很多组件的我们来说可能就麻烦了,去找组件啥啥啥,但是小编觉得,是的,组件或许能帮我们实现这么个需求,但是我们难道没有别的方法了吗?
  • 原生标签:input!!!小编回忆,最开始学习html的时候有个标签input,小编也不绕圈了,设置type="file"就是文件上传的按钮!!

  • 回忆一下,看如下文档:

HTML input type 属性 | 菜鸟教程

第三章 解决需求 

  • 好了,用到的工具有了,现在的问题在于如何解决我们利用导入的按钮操作文件上传的按钮?
  • 思路:小编为按钮与input都绑定唯一识别的ref(vue)/id(正常的html页面)以及click点击事件,原生js会告诉我们,当我们绑定id时,获取到DOM之后,我们能通过DOM.click获取到DOM上绑定的点击事件。问题解决!
  • 大家根据小编的代码理解逻辑:(小编会逐步解释的) 

html: 

// 这里是element-ui的button组件
<el-button v-if="hasPermission('book:book:import')" // 通过权限控制图标显示隐藏(可忽略)type="text" //button的type(可忽略)icon="el-icon-import" // 图标类名(可忽略)size="small" // 尺寸@click="toImportBookList(scope.row.id)"> // 按钮的点击事件,传的参数是该行数据的id导入</el-button>
// 原生的input
<input type="file" // 上传文件的类型accept=".xls,.xlsx" // 限制上传的文件格式:ref="`upload-book-list-file-${scope.row.id}`"  // 唯一识别的ref,利用id使得渲染时ref不重名style="display: block" // 控制该标签的显示隐藏@click="importBookList(scope.row.id)"> // 该标签的点击事件

js:(注意一定要理解思路,而不是直接拷贝代码)

export default {methods: { // vue:方法toImportBookList (id) { // 按钮的点击事件const bookListFileUplodDom = this.$refs[`upload-book-list-file-${id}`] // 通过$refs获取对应的input标签bookListFileUplodDom.click() // 注意这句代码,他就是通过dom调用自身的点击事件},importBookList (id) { // input标签的点击事件const _this = thisconst bookListFileUplodDom = this.$refs[`upload-book-list-file-${id}`] // 通过$refs获取input标签bookListFileUplodDom.addEventListener('change', function (e) { // input标签监听事件,当input发生变化时说明文件要么上传了,要么删除了,上传成功执行如下代码const file = bookListFileUplodDom.files[0] // 该方法只针对input、type="file"或者图片,才能使用他获取到file的二进制流const formBody = new FormData() // 这里的formData小编就不多说了,已经用到很多次了,小编会有单独的详细的文章做讲解formBody.append('file', file)formBody.append('id', id)this.loading = true // 添加加载中(可忽略)bookService.importBook(formBody).then(({data}) => { // 这里是发送请求系列信息,仅供参考this.$message.success({ // 请求成功后返回信息dangerouslyUseHTMLString: true,message: data})this.refreshList() // 刷新列表}).catch(err => { // 出错了则捕获错误this.loading = false // 隐藏加载中console.log('出错了', err)})}, false)}}
}

第四章 优化代码

  • 使用e.stopPropagation()

阻止事件冒泡,使用addEventListener,三个参数,第三个参数小编设置了false,表示的是事件冒泡,由里向外触发,子元素的点击事件触发之后,之后还会触发父元素的点击事件,从而导致我们点击事件执行到不需要执行的事件,触发顺序:children -> parent -> body,添加e.stopPropagation()就只会执行我们点击的标签的点击事件。代码如下:

bookListFileUplodDom.addEventListener('change', function (e) {e.stopPropagation() // 阻止冒泡事件(注意该方法写在代码前面)……(其余代码逻辑)
}, false)
  • addEventListener我们注册的监听'change'函数有两种情况:当上传文件成功时,input变化了,会执行代码,然后向发送请求,当然,当我们删除文件时,文件都为空了,还需要执行代码,向后端发请求吗?所以需要我们判断一下,当删除文件时,不执行代码,不向后端发送请求

 

 通过输出可以看到,删除文件时,file拿到的值是undefined,那么我们就能通过判断来解决该问题了,代码如下:

bookListFileUplodDom.addEventListener('change', function (e) {e.stopPropagation() // 阻止冒泡事件(注意该方法写在代码前面)const file = bookListFileUplodDom.files[0]if(file){ // 只有当file有数据时才执行如下逻辑……(其余代码逻辑)}
}, false)
  •  addEventListener注册了还需要removeEventListener移除事件,如何removeEventListener移除呢,在哪移除呢,解决方法在下一章节

第五章 解决问题

  • 查看问题,不如不添加removeEventListener的效果,当我们执行多次导入时,也就相当于注册了很多个addEventListener('change',function(e){})事件,就会造成当我们只执行一次有效操作时,多个监听开始执行,导致最终前端会发送多个相同的请求

 

  • (这里直接给出小编的最终解决完成的源代码,如果大家进一步知道原理,小编会在下一篇文章中说明原因,做详细的解释!)
  • 原理看该文章

js基础:addEventListener与removeEventListener使用时,涉及的问题(包括事件捕获、冒泡,removeEventListener不生效问题)-CSDN博客

<script>let bookListHandler = null // 定义一个自变量的等待赋值(移除监听函数使用)export default {methods: {toImportBookList (id) {const bookListFileUplodDom = this.$refs[`upload-book-list-file-${id}`]bookListFileUplodDom.removeEventListener('change', bookListHandler, false) // 每次调用函数执行移除上一次的添加的监听bookListFileUplodDom.click()},importBookList (id) {const _this = thisconst bookListFileUplodDom = this.$refs[`upload-book-list-file-${id}`]console.log('bookListFileUplodDom', bookListFileUplodDom)bookListHandler = function (e) { // 将执行的监听函数赋值e.stopPropagation()_this.getBookList(id, bookListFileUplodDom)}bookListFileUplodDom.addEventListener('change', bookListHandler, false) // 添加监听事件},getBookList (id, bookListFileUplodDom) {const file = bookListFileUplodDom.files[0]console.log('file', file)if (file) {const formBody = new FormData()formBody.append('file', file)formBody.append('id', id)this.loading = truebookService.importBook(formBody).then(({data}) => {this.$message.success({dangerouslyUseHTMLString: true,message: data})this.refreshList()}).catch(err => {this.loading = falseconsole.log('出错了', err)})}},}
}
</script>

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

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

相关文章

【已解决】taos时序数据库3.0版本,怎么按照时间分组?

taos数据库中按照时间分组&#xff0c;在2.4版本时候可以直接使用INTERVAL(time_unit)来查询。例如 前面可以直接添加_ts的。但是在3.0版本之后&#xff0c;如果直接使用的话&#xff0c;只会返回count&#xff1a; 没有前面的时间。那么在3.0版本时候&#xff0c;怎么修改呢&a…

在mt4上怎么查看CHFJPY品种的合约细则?

在MetaTrader 4 (MT4) 上查看CHFJPY品种的合约细则的方法如下&#xff1a; FXCM福汇官方个人注册登录流程 1.打开MT4软件并登录到您的交易账户。 2.在MT4界面的"市场观察"窗格中&#xff0c;找到并右键单击"CHFJPY"货币对。如果您无法找到"市场观察…

时间是如何定义的

每年365天&#xff0c;每天24小时&#xff0c;每小时60分钟&#xff0c;每分钟60s&#xff0c;这是我们习以为常的时间计量单位&#xff0c;那么在继续往下&#xff0c;1s是多少&#xff1f;几时几刻、几点几分是如何确定的&#xff1f;带着这些问题&#xff0c;展开本文。 1、…

常见分布的分布列/概率密度、分布函数、期望、方差、特征函数

0-1分布 二项分布 泊松分布 几何分布 均匀分布 正态分布 指数分布 伽马分布 卡方分布

2023.12.18 关于 CentOS7 安装 Redis5

目录 安装步骤 创建符号连接 修改配置文件 启动 redis 服务器 停止 redis 服务器 安装步骤 CentOS7 的 yum 仓库中&#xff0c;redis 的默认版本为 3 系列为了 能让 CentOS7 安装上 Redis5&#xff0c;此处我们需要安装额外软件源 1、安装额外软件源 yum install cento…

腾讯云消息队列11月产品月报 | RocketMQ 5.x 国际站上线

2023年 11月动态 消息队列 RocketMQ 版 1、5.x 形态国际站上线 国际站上线 5.x 集群全系列&#xff0c;第一批先开放新加坡和硅谷地域。 控制台链接&#xff1a;https://console.tencentcloud.com/trocketmq 2、 无感迁移能力 支持用户白屏化操作&#xff0c;将自建的 Roc…

提前预判和确认再做 现货白银投资的两种思路

在现货白银投资中&#xff0c;对于交易的步骤长期有两种看法。一种是提前预判行情并提前布局。另外一种是等待行情启动再做布局。这种两种方法要怎么选呢&#xff1f;笔者将从自己的角度出发&#xff0c;对这个问题进行讨论。 我们来看一下前一种的投资者&#xff0c;他们喜欢提…

标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”

各位CSDN的uu们好呀&#xff0c;今天&#xff0c;继续小雅兰西嘎嘎的学习&#xff0c;标准库中的string类&#xff0c;下面&#xff0c;让我们一起进入西嘎嘎string的世界吧&#xff01;&#xff01;&#xff01; string类的常用接口说明 Leetcode每日一题 string类的常用接口…

pip 常用指令 pip install 命令用法介绍

pip install 是一个 Python 包管理器命令&#xff0c;用于安装 Python 包。pip 是 Python 的一个重要工具&#xff0c;可以用来安装、升级和卸载 Python 包。 pip install 命令的一些常见参数有 -r&#xff1a;从一个需求文件中安装所有的包。-U 或 --upgrade&#xff1a;升级…

鸿蒙开发基本概念

1、开发准备 1.1、UI框架 HarmonyOS提供了一套UI开发框架&#xff0c;即方舟开发框架&#xff08;ArkUI框架&#xff09;。方舟开发框架可为开发者提供应用UI开发所必需的能力&#xff0c;比如多种组件、布局计算、动画能力、UI交互、绘制等。 方舟开发框架针对不同目的和技术…

基于MLP完成CIFAR-10数据集和UCI wine数据集的分类

基于MLP完成CIFAR-10数据集和UCI wine数据集的分类&#xff0c;使用到了sklearn和tensorflow&#xff0c;并对图片分类进行了数据可视化展示 数据集介绍 UCI wine数据集&#xff1a; http://archive.ics.uci.edu/dataset/109/wine 这些数据是对意大利同一地区种植的葡萄酒进…

[SWPUCTF 2021 新生赛]jicao

首先打开环境 代码审计&#xff0c;他这儿需要进行GET传参和POST传参&#xff0c;需要进行POST请求 变量idwllmNB&#xff0c;进行GET请求变量json里需要含参数x以及jsonwllm 构造 得到flag

在线更换Proxmox VE超融合集群Ceph OSD磁盘

因为资源紧张的原因&#xff0c;担心一旦关机&#xff0c;虚拟机因为没有空闲的资源而被冻结&#xff0c;以致于不能漂移&#xff0c;导致部分服务停止&#xff0c;只好让机房帮忙热插拔。 幸运的是&#xff0c;插上去能够被系统所识别&#xff08;/dev/sdf就是新插入的硬盘&am…

华为数通方向HCIP-DataCom H12-831题库(多选题:181-200)

第181题 如图所示,R1、R2、R3、R4都部署为SPF区域0,链路的cost值如图中标识。R1、R2R3、R4的Loopback0通告入OSPF。R1、R2、R3与R4使用Loopback0作为连接接口,建立BGP对等体关系,其中R4为RR设备,R1、R2、R3是R4的客户端。当R4的直连地址172.20,1,4/32通告入BGP后,以下关R…

mysql部署 --(docker)

先查找MySQL 镜像 Docker search mysql &#xff1b; 拉取mysql镜像&#xff0c;默认拉取最新的&#xff1b; 创建mysql容器&#xff0c;-p 代表端口映射&#xff0c;格式为 宿主机端口&#xff1a;容器运行端口 -e 代表添加环境变量&#xff0c;MYSQL_ROOT_PASSWORD是root用户…

2024云渲染平台推荐!免费云渲染平台(注册账号)推荐

近期&#xff0c;由于信息科技和云计算的迅猛发展&#xff0c;云渲染服务也逐步蓬勃发展并已达到成熟阶段&#xff0c;它因其高效办公、成本效益优越以及操作简便易行&#xff0c;赢得了广大设计师和 CG 艺术家的热烈欢迎&#xff0c;在过去的岁月里&#xff0c;创造一张高清晰…

OpenCV技术应用(8)— 如何将视频分解

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本节课就手把手教大家如何将一幅图像转化成热力图&#xff0c;希望大家学习之后能够有所收获~&#xff01;&#x1f308; 目录 &#x1f680;1.技术介绍 &#x1f680;2.实现代码 &#x1f680;1.技术介绍 视频是…

charles和谷歌浏览器在Mac上进行软件安装,桌面上会显示一个虚拟磁盘,关掉页面推出磁盘内容都消失掉了 需要再次安装问题解决

其他软件也会有这种情况&#xff0c;这里我们以charles为例。绿色背景的内容是重点步骤。 1.如图&#xff0c;我下载了一个charles一个版本的dmg文件。 2.打开后&#xff0c;选择Agree 3.桌面会出现一个磁盘和如下页面 4.错误操作------可以不看 直接看第5步正确操作 常规情…

Socket.D 基于消息的响应式应用层网络协议

首先根据 Socket.D 官网的副标题&#xff0c;Socket.D 的自我定义是&#xff1a; 基于事件和语义消息流的网络应用协议。官网定义的特点是&#xff1a; 基于事件&#xff0c;每个消息都可事件路由所谓语义&#xff0c;通过元信息进行语义描述流关联性&#xff0c;有相关的消息…

Android Studio设置android:background 属性背景颜色

除了默认的颜色之外都要自己添加。 添加颜色的操作步骤&#xff1a; 打开res文件夹&#xff0c;找values&#xff0c;里面有个colors.xml的文件。然后在里面定义一些颜色。 完成