首页 > 其他分享 >elementUI中点击触发两次点击事件原理及解决方法

elementUI中点击触发两次点击事件原理及解决方法

时间:2024-03-19 17:14:43浏览次数:33  
标签:触发 elementUI label 点击 事件 input click

​ 最近在研究vue3,在学习vue3和element-plus的过程中,突然发现el-radio的一个问题,element的版本号如下

"element-plus": "2.2.27",

​ 代码如下:

<template>
	<div class="button-group">
        <el-radio-group v-model="buttonGroup">
          <el-radio-button label="本周热点" @click="handleBtnGroup('本周热点', $event)"/>
          <el-radio-button label="专题分析" @click="handleBtnGroup('专题分析', $event)"/>
          <el-radio-button label="指标收藏" @click="handleBtnGroup('指标收藏', $event)"/>
          <el-radio-button label="历史记录" @click="handleBtnGroup('历史记录', $event)"/>
        </el-radio-group>
    </div>
</template>

<script setup name="chatbiIndex">
    //按钮组当前按钮选择
	let buttonGroup = ref('')
    //控制单选框方法
    function handleBtnGroup(btnName,e){
      if(buttonGroup.value == btnName){
        buttonGroup.value = ""
      } else {
        buttonGroup.value = btnName
      }
    }
</script>

​ 这段代码很好理解,本意是控制单选框点击一下选中,如果第二次点击同一个单选框则取消选择,但是在执行的时候发现点击之后单选框并不会被选中,buttonGroup的值依然为空字符串,使用console.log(e)打印后发现结果如下:

​ 很明显函数被执行两次,根据逻辑如果第二次触发的是同一个按钮则会取消选择,那么问题来了,明明我只是点击了一次,为什么函数会被执行两次呢。

​ 于是我先查看element-plus中radio-button.vue文件的部分源码,源码如下

<template>
  <label
    :class="[
      ns.b('button'),
      ns.is('active', modelValue === actualValue),
      ns.is('disabled', disabled),
      ns.is('focus', focus),
      ns.bm('button', size),
    ]"
  >
    <input
      ref="radioRef"
      v-model="modelValue"
      :class="ns.be('button', 'original-radio')"
      :value="actualValue"
      type="radio"
      :name="name || radioGroup?.name"
      :disabled="disabled"
      @focus="focus = true"
      @blur="focus = false"
    />
    <span
      :class="ns.be('button', 'inner')"
      :style="modelValue === actualValue ? activeStyle : {}"
      @keydown.stop
    >
      <slot>
        {{ label }}
      </slot>
    </span>
  </label>
</template>

​ 从源码中可以看出来,这个组件内部由input和span组成,根元素是一个和input联动的label,然后再根据我观察的触发两次的元素来看,span是正常点击的,而input则可能是自动触发的,打开input打印的click结果就可以看出来:

​ 这一切看起来很复杂,但是只要慢慢理清思路就很好理解。

​ 首先我们将@click事件绑定在了el-radio-button这个组件上,因为vue3和vue2不同,vue3是默认原生事件,如果在子组件内使用defineEmits定义了自定义事件,才会转为自定义事件,很显然element并没有定义,所以我们走的原生事件。

​ 那么这个click的原生事件就会绑定在el-radio-button组件的根元素也就是label上,然后因为事件冒泡机制,当label里面的input或者span元素被点击时,也会触发这个click事件。

​ 关键的来了,因为input在源码中绑定了v-model,如果看过vue的文档就会知道,v-model的实现主要是靠v-bindv-on两个指令共同实现:

​ 所以我们合理推断,<input type=radio>元素中的v-model肯定是:value加上@click

​ 我们都知道,被label包裹的<input type=radio>元素,如果label被点击,则视为input被点击,而又因为input的click事件被label冒泡的click事件代替了,导致在点击span或者label(其实都是触发的label身上的点击事件)时,input自身也会执行一次click事件,因而触发了两次我们写的click对应的handleBtnGroup函数。

​ 当然,上述都是我的猜想,事实是否真的是这样,我们写个简单的代码段就明白了。

<label @click="test">测试 
    <input type="radio" v-model="buttonGroup" value="测试" name="一号"> <span>二号</span> 
</label>
......
......
function test(e){
  console.log(e)
}

​ 页面如下:

​ 这是点击测试所打印的结果

​ 这是点击二号所打印的结果

​ 这是点击一号,也就是input元素打印的结果

​ 以上试验说明input函数中的click确实被冒泡事件替换,而且点击label或者span确实会导致input自身自动触发一次click,我们的猜想是正确的.

​ 那么该如何解决这一切呢,其实很简单,因为input的click事件改变的原因是冒泡导致的,那么只要input不被冒泡影响就可以了,改动代码如下:

<label @click="test">测试 <input type="radio" v-model="buttonGroup" @click.stop value="测试" name="一号"> <span>二号</span> </label>

​ 阻止冒泡确实有效,具体打印结果我不再截图,有兴趣的朋友可以自己试试。

​ 其实官方在新版本中也已经修复了该bug,2.3.10版本及以上没有该bug。

​ 那么问题来了,有些朋友比如我,使用的是2.3.10版本以下的该如何解决呢,网上也有一些办法,比如在触发click的时候判断点击的target是哪个元素,但是都比较麻烦,其实我们完全可以从源头入手,在最开始写给el-radio-button组件的click后面加上prevent修饰符:

<el-radio-group v-model="buttonGroup">
  <el-radio-button label="本周热点" @click.prevent="handleBtnGroup('本周热点', $event)"/>
  <el-radio-button label="专题分析" @click.prevent="handleBtnGroup('专题分析', $event)"/>
  <el-radio-button label="指标收藏" @click.prevent="handleBtnGroup('指标收藏', $event)"/>
  <el-radio-button label="历史记录" @click.prevent="handleBtnGroup('历史记录', $event)"/>
</el-radio-group>

​ 原理是阻止input触发自己的默认事件,也就是label被点击时算作input被点击。

标签:触发,elementUI,label,点击,事件,input,click
From: https://www.cnblogs.com/sakura-hfhj/p/18083376

相关文章

  • elementui 表格复选框根据列表状态设置禁用效果
    el-table表格type="selection"复选框需要根据状态来设置是否禁用,需要加selectable属性返回为false时则为禁用注意selectable要是一个方法不能设置变量checkSelectable(row){if(row.status==="0"){returntrue;}else{......
  • 【Lazy ORM】 小工具 acw 本地客户端 你负责点击页面,他负责输出代码
    介绍wu-smart-acw-client简称acw-client,是一个基于LazyORM定制的客户端代码生成小工具LazyORM小工具acw本地客户端你负责点击页面,他负责输出代码安装<dependency><groupId>top.wu2020</groupId><artifactId>wu-smart-acw-cli......
  • matinal:SAP ABAP OO面向对象编程中的触发和处理事件
    ......
  • echarts实践总结(常用一):柱状图(特点:渐变色、点击缩放、左右滑动、悬浮展示样式)
    目录第一章echarts基本使用第二章echarts实践——柱状图效果展示第一章echarts基本使用Echarts常用配置项(详细入门)_echarts配置项手册-CSDN博客第二章echarts实践——柱状图最近接到这么一个需求,需要画页面,然后有这么几个echarts的图需要画,平常我们通过教程......
  • 利用 STM32 TIMER 触发 ADC 实现分组转换
    1、问题描述使用STM32G4系列芯片开发产品,用到其中一个ADC模块的多个通道,他希望使用TIMER来定时触发这几个通道的转换。不过他有两点疑惑。第一,他期望定时器触发这几个通道是每触发一次则只转换一个通道,这样依次触发转换,而不是触发一次就把几个通道都转换完结。他......
  • MogDB-openGauss触发器简介(1)
    MogDB/opengauss触发器简介(1)触发器是对应用动作的响应机制,当应用对一个对象发起DML操作时,就会产生一个触发事件(Event)。如果该对象上拥有该事件对应的触发器,那么就会检查触发器的触发条件(Condition)是否满足,如果满足触发条件,那么就会执行触发动作(Action)。事件:触发器的触发事......
  • el-menu 点击有子元素的菜单项字体变色
    效果图: el-menu组件只是在点击跟元素时,根元素变色,如图:.el-menu-item.is-active{background-color:rgb(56,96,226)!important;color:white;} 点击有子元素的菜单时不会变色,下面可以实现:(点击有子元素菜单时,会有一个class属性is-opened,所以给其编辑样式即......
  • MogDB-openGauss触发器简介(2)
    MogDB/opengauss触发器简介(2)针对触发对象的触发事件一旦发生,就会激活触发器,触发器首先会检查触发条件,只有在满足触发条件的情况下,才会被真正地执行。其中元组级的触发器可以将更新前后的值嵌入到触发器的触发条件中。NEW.column_name:UPDATE或INSERT事件对应“新”元组,colu......
  • vue3 引入 ElementUI
     vue3使用elementUI会报错,需要引入elementUIPlus。Plus官网:https://element-plus.gitee.io/zh-CN/guide/quickstart.htmlUI官网:https://element.eleme.cn/#/zh-CN/component/installation1.安装ElementUIPlusnpminstallelement-plus--savepackage.json检查。......
  • 考虑功率均分与电压频率的事件触发分布式二次控制MATLAB模型
    微❤关注“电气仔推送”获得资料(专享优惠)模型简介此模型是在《基于事件触发机制的孤岛微电网二次电压与频率协同控制MATLAB仿真模型》上进一步创作的,之前的模型只考虑了二次电压与频率控制,并没有考虑均分这一项点。因此此模型在事件触发机制的基础上,继续创作了基于事件触发......