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

目录

第一章 接到需求

第二章 了解需求

第三章 解决需求 

第四章 优化代码

第五章 解决问题


第一章 接到需求

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

经理说需求了:这里有两个按钮,一个是导入文件的,一个是导入机构的,你看看怎么把这按钮功能实现,把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 = this
      const 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 = this
      const 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 = true
        bookService.importBook(formBody).then(({data}) => {
          this.$message.success({
            dangerouslyUseHTMLString: true,
            message: data
          })
          this.refreshList()
        }).catch(err => {
          this.loading = false
          console.log('出错了', err)
        })
      }
    },
  }
}
</script>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flex布局下居中滚动溢出

摘要&#xff1a; 遇到一个需求&#xff0c;在uniapp swiper下实现轮播图&#xff0c;图片的高度是自适应的&#xff0c;超出屏幕设备的高度的时候&#xff0c;滚动显示全部&#xff0c;图片的高度没有超过屏幕的高度时候&#xff0c;上下居中于屏幕的中间&#xff01;下面写了…

长短期记忆(LSTM)神经网络-多输入回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分程序&#xff1a; 四、完整代码数据下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平台编…

2023中国品牌节金谱奖荣誉发布 酷开科技获颁OTT行业科技创新奖

11月17日—19日&#xff0c;以“复苏与腾飞”为主题的2023第十七届中国品牌节&#xff0c;在杭州市云栖小镇国际会展中心成功举行。在18日晚间的荣耀盛典上&#xff0c;“TopBrand 2023中国品牌节金谱奖”荣誉发布&#xff0c;酷开科技斩获OTT行业科技创新奖。 酷开科技作为OTT…

九牧:科技卫浴,长期主义

“没有做错什么&#xff0c;但却输给了时代”&#xff0c;这是人们给当年手机巨头诺基亚的注解。 谁也没有想到&#xff0c;曾在手机行业称雄的诺基亚&#xff0c;最终败给了时代。当年&#xff0c;在2G向3G、4G跨越的时候&#xff0c;苹果、微软的iOS和安卓系统将手机从简单的…

PHPStorm一站式配置

phpstorm安装好之后&#xff0c;先别急着编码。工欲善其事&#xff0c;必先利其器&#xff0c;配置好下面这些之后让编码事半功倍。 主题 Appearance & Behavior -> Appearance -> Theme 选中 [Light with Light Header] 亮色较为护眼 关闭更新 Appearance & …

什么是同源策略?

同源 同源指的是URL有相同的协议、主机名和端口号。 同源策略 同源策略指的是浏览器提供的安全功能&#xff0c;非同源的RUL之间不能进行资源交互 跨域 两个非同源之间要进行资源交互就是跨域。 浏览器对跨域请求的拦截 浏览器是允许跨域请求的&#xff0c;但是请求返回…

零刻EQ12 N100 双2.5G网口 All In One新手教程

零刻EQ12 N100 双2.5G网口 All In One新手教程 前言1.硬件配置2.准备工作2.1. ESXI8.0U2镜像2.2. Rufus磁盘工具下载2.3. ikuai镜像下载2.4. StarWindConverter虚拟磁盘格式转换工具下载2.5. OpenWrt镜像下载2.6. 黑群晖RR引导镜像下载(DSM7.2)2.7. 需要准备的硬件2.8. 格式化需…

《空气质量持续改善行动计划》发布,汉威科技助力蓝天保卫战

近日&#xff0c;国务院印发《空气质量持续改善行动计划》&#xff0c;这是继2013年“大气十条”之后的第三个国家层面的保卫蓝天行动计划。 计划要求协同推进降碳、减污、扩绿、增长&#xff0c;以改善空气质量为核心&#xff0c;以减少重污染天气和解决人民群众身边的突出大…

什么是云服务器ECS

云服务器ECS&#xff08;Elastic Compute Service&#xff09;是阿里云提供的性能卓越、稳定可靠、弹性扩展的IaaS&#xff08;Infrastructure as a Service&#xff09;级别云计算服务。云服务器ECS免去了您采购IT硬件的前期准备&#xff0c;让您像使用水、电、天然气等公共资…

Python 爬虫之简单的爬虫(四)

爬取动态网页&#xff08;下&#xff09; 文章目录 爬取动态网页&#xff08;下&#xff09;前言一、大致内容二、基本思路三、代码编写1.引入库2.加载网页数据3.获取并保存4.保存文档 总结 前言 上篇主要讲了如何去爬取数据&#xff0c;这篇来讲一下如何在获取的同时将数据整…

机器学习 | 贝叶斯方法

不同于KNN最近邻算法的空间思维&#xff0c;线性算法的线性思维&#xff0c;决策树算法的树状思维&#xff0c;神经网络的网状思维&#xff0c;SVM的升维思维。 贝叶斯方法强调的是 先后的因果思维。 监督式模型分为判别式模型和生成式模型。 判别模型和生成模型的区别&#xf…

英码科技受邀参加2023计算产业生态大会,分享智慧轨道交通创新解决方案

12月13-14日&#xff0c;“凝心聚力&#xff0c;共赢计算新时代”——2023计算产业生态大会在北京香格里拉饭店成功举办。英码科技受邀参加行业数字化分论坛活动&#xff0c;市场总监李甘来先生现场发表了题为《AI哨兵&#xff0c;为铁路安全运营站好第一道岗》的精彩主题演讲&…

PIL/Pillow

Abstract PIL(Python Imaging Library)是一个用于图像处理的 Python 库。它提供了广泛的功能&#xff0c;包括图像加载、保存、调整大小、裁剪、旋转、滤镜应用等。 由于 PIL 的开发停止在 2009 年&#xff0c;因此推荐使用其后续的维护版本 Pillow。Pillow 是一个兼容 PIL 接…

Vue3+el-table实现甘特图

Vue3 el-table实现甘特图效果 代码gitee 整体实现效果如下 进度列&#xff0c;可以通过设置天或小时&#xff0c;切换不同列显示类型。 涉及到的问题 1、通过Worker解决js线程堵塞问题 在根据时间动态生成列时&#xff0c;由于开始时间与结束时间跨度过大时&#xff0c;计…

【从服务器获取共享列表失败】【无法与设备或资源通信】解决方案!

【从服务器获取共享列表失败】背景&#xff1a; 某项目搭建有samba共享&#xff0c;使用一段时间后&#xff0c;不知何种原因&#xff0c;客户端链接共享时报&#xff1a;从服务器获取共享列表失败&#xff0c;无效的参数。 可参考解决方案A&#xff1a; 银河麒麟samba共享文…

vue3 环境变量

开发环境&#xff1a; .env.development VITE_HTTPhttp://www.baidu.com生成环境&#xff1a; .env.production VITE_HTTPhttp://www.jd.com获取环境里的值 <template></template><script setup lang"ts"> console.log(import.meta.env); <…

图片处理软件DxO PhotoLab 6 mac高级工具

DxO PhotoLab 6 mac是一款专业的RAW图片处理软件&#xff0c;适用于Mac操作系统。它具有先进的图像处理技术和直观易用的界面&#xff0c;可帮助用户轻松地将RAW格式的照片转换为高质量的JPEG或TIFF图像。 DxO PhotoLab 6支持多种相机品牌的RAW格式&#xff0c;包括佳能、尼康、…

【docker】数据管理

Docker容器会随时关闭和开启,Docker 容器的数据放哪里呢&#xff1f; 答案就是&#xff1a;数据卷和数据卷容器 官网文档 Manage data in Docker | Docker Docs 数据卷(Data Volume) 数据卷就是将宿主机的某个目录&#xff0c;映射到容器中&#xff0c;作为数据存储的目录&…

21 3GPP中 5G NR高速列车通信标准化

文章目录 信道模型实验——物理层设计相关元素μ(与子载波间隔有关)设计参考信号(DMRS) 本文提出初始接入、移动性管理、线性小区设计等高层技术。描述3GPP采用HST场景的评估参数&#xff0c;阐释了HST应用的物理层技术&#xff0c;包括数字通信和参考信号设计&#xff0c;链路…

基于PHP的蛋糕购物商城系统

有需要请加文章底部Q哦 可远程调试 基于PHP的蛋糕购物商城系统 一 介绍 此蛋糕购物商城基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈&#xff1a;phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销…