Vue在chrome44偶现点击子元素事件无法冒泡的解决方法


Posted in Javascript onDecember 15, 2019

前言

公司的一个项目大致是这样的:一个左侧列表,点击左侧列表的文章标题,右侧展开该文章对应的内容的。
现在的问题出现在极少部分客户有时左侧的标题,无法打开对应的右侧的内容,给人的改进就是‘卡'、点不动、点了没反应。

再大致介绍下项目环境:

chrome 44(打包到用户客户端内)
Vue 2.6.10

左侧列表布局

Vue在chrome44偶现点击子元素事件无法冒泡的解决方法

列表的每个绿色方框是一个vue组件,名叫ListItem,列表的组件叫List

代码类似这样

// List.vue
<template>
 <div class="blue">
  <list-item v-for="item in dataList" :data="item" @click="handleClick">
 </div>
</template>
<script>
 export default {
  ...
  methods: {
   handleClick() {
    ... 请求文章内容相应的逻辑
   }
  }
 }
</script>
// ListItem.vue
<template>
 <div class="green" @click="onClick">
  <div class="red circle"></div>
  <div class="red square">
   <div class="yellow square1"></div>
   <div class="yellow square2"></div>
  </div>
 </div>
</template>
<script>
 export default {
  ...
  methods: {
   onClick(e) {
    console.log('点击', e.target);
    this.$emit('click');
   }
  }
 }
</script>

首先大家不要评论这个click是不是多此一举,为什么不直接在Lisit.vue里面写@click.native="handleClick" 。原项目就是这样写的,其中的部分逻辑我简化了,最重要的是这个不是我们讨论的重点。

根据上面的代码我们只要在绿色的方框内点击,均可以实现请求文章内容。实测也是没有问题的,但是上线以来,有部分用户报障“文章列表点不动(其实就是onClick -> handleClick没有调用”,作为开始说实话一开始是不信,这么简单的逻辑,这时vue的常规操作好吗,怎么可能有问题。

但是经过远程和实地确认,确实是有这样的问题。

经过调查发现,当点击上图红色圆圈下方时,是可以触发onClick的。其实此时是刚好直接点到绿方框这个元素了,也就是说我们直接点到绑定了点击事件的div上时是可以触发onClick。我们的第一反应是这<div class="green">的子元素是否使用了阻止冒泡,可惜没有,如果有,开发自测和测试人员测试早就会发现,该问题不可能到线上才被发现。

我们有怀疑是除了click以外其他事件的影响,比如mousedown、mouseup被阻止冒泡,是否存在使用事件捕获并且还阻止冒泡的情况,经过排除后,发现是有一部分的,按照宁愿错杀不能漏杀的原则,我们针对这些事件都进行调整,但是是否真的解决了这个问题,我们不知道,因为这个问题我们开发人员本地、测试人员在测试环境和生产环境均无法复现。每次只能在发版的时候带上去一点点改动,改动的前提是不保证能改好,但是一定不会改坏,面对客户的报障我们只能叫他们用临时的解决方案,也是点击红色圆圈下面那块区域。

有一次我们增加了在红色圆圈和红色方框上绑定同一个事件,也就是

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
  (adsbygoogle = window.adsbygoogle || []).push({
   google_ad_client: "ca-pub-3013839362871866",
   enable_page_level_ads: true
  });
</script>
// ListItem.vue
<template>
 <div class="green" @click="onClick">
  <div class="red circle" @click="onClick"></div>
  <div class="red square" @click="onClick">
   <div class="yellow square1"></div>
   <div class="yellow square2"></div>
  </div>
 </div>
</template>

是的,我们就差在<div class="yellow square1"><div class="yellow square2">也绑上点击事件了。我们太难了。。。

这样上线后依然有问题,大家应该料到了,如果那些用户点到了
<div class="yellow square1"><div class="yellow square2">上依然是无法触发onClick的,作为一个程序员,我们绝不容忍在每个div上绑定同样的事件啊,我们放弃了这样的改动,做个有尊严的程序员,不是吗?

在用户发生“点不动”的时候,我们实体去看的时候发现:

1.我们在调试工具里面将所有的dom上绑定的事件都移除,只保留自己绑定的<div class="green" @click="onClick">这一个事件,用户依然“点不动”,依然只有点击红圈才能触发onClick。
2.我们在控制台使用document.querySelect('.yellow .square1').click()的方式是可以触发onClick的,也就是该点击事件其实是可以冒泡到<div class="green">的。

为什么我们用鼠标点击就不行了,并且通过在控制打印出我们点击的元素,我们可以100%确定我们用鼠标点击的就是document.querySelect('.yellow .square1')所对应的这个元素。

这个发现完全颠覆了我们的认知。到底是哪里错了,要么是Vue,要么是浏览器,都是大佬啊,它们错了?其他人都在用,都没毛病啊,并且这个问题无法复现,没有必现流程,使用按键精灵模拟用户操作了一天也没有复现。怎么跟其他人,大家只会觉得你连这么简单的问题都搞不定?代码也给很多前端同事、前端大佬review过了,没毛病啊。但是生产上就是有人使用时会出现“点不动”,这是事实啊。

浏览器是前端的根基,我们我只能开始大胆怀疑下是Vue的问题,或者我们的用法有问题(怎么用没有问题),或者说这个版本的Vue在这个版本的Chrome44在部分场景中有问题。

搜了vue event propagation相关的内容,有一点小小的发现,之前确实有人反映过Vue 2.4.2在子元素事件冒泡相关的issue,并且vue的源码里面也有相关的注释。

Vue在chrome44偶现点击子元素事件无法冒泡的解决方法

虽然上面提到的 #6566 issue并非跟我们的问题一模一样,但是既然有个提过这类bug,我们更有里有相信可能是Vue的问题(或者说我们用的不对)了

最后我们决定放弃这个用Vue写的点击事件的写法,改用jQuery了。
在上面列表的<div class="blue"></div>上绑定事件,然后根据对应的文章id来实现打开对应文章的目的,这一部分没什么技术含量,就不细说了。

是的,最终我们放弃了寻找这个问题的原因了,面对用户的频繁报障,再加上我们无法复现问题,根本不知道改好了没有,我们也不可能频繁发版在生产上让用户帮我们测试(测试人员第一个不答应)。

这个到底解决好了没有,从理论上应该是没问题了,但是我们说了不算,就看客户还有没有这样的报障了,毕竟得靠他们来验证。

一个灵异问题从入门到放弃,我们终于把Vue彻底用成了我们讨厌的样子。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
在JavaScript中遭遇级联表达式陷阱
Mar 08 Javascript
extjs 学习笔记(二) Ext.Element类
Oct 13 Javascript
利用JS重写Cognos右键菜单的实现代码
Apr 11 Javascript
一个简单的js渐显(fadeIn)渐隐(fadeOut)类
Jun 19 Javascript
JS控制文本框textarea输入字数限制的方法
Jun 17 Javascript
以JSON形式将JS中Array对象数组传至后台的方法
Jan 06 Javascript
jQuery实现textarea自动增长宽高的方法
Dec 18 Javascript
关于在Servelet中如何获取当前时间的操作方法
Jun 28 Javascript
JavaScript轻松创建级联函数的方法示例
Feb 10 Javascript
JS面试题大坑之隐式类型转换实例代码
Oct 14 Javascript
vue 数字翻牌器动态加载数据
Apr 20 Vue.js
JS开发前端团队展示控制器来为成员引流
Aug 14 Javascript
Angular6项目打包优化的实现方法
Dec 15 #Javascript
vue+elementUI组件table实现前端分页功能
Nov 15 #Javascript
Vue+ElementUI table实现表格分页
Dec 14 #Javascript
微信小程序跨页面传递data数据方法解析
Dec 13 #Javascript
微信小程序swiper使用网络图片不显示问题解决
Dec 13 #Javascript
JS实现移动端双指缩放和旋转方法
Dec 13 #Javascript
微信小程序返回上一页传参并刷新过程解析
Dec 13 #Javascript
You might like
Zend Framework入门教程之Zend_Db数据库操作详解
2016/12/08 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
PHP函数积累总结
2019/03/19 PHP
关于laravel后台模板laravel-admin select框的使用详解
2019/10/03 PHP
通过jquery的$.getJSON做一个跨域ajax请求试验
2011/05/03 Javascript
简单谈谈jQuery(function(){})与(function(){})(jQuery)
2014/12/19 Javascript
简单的jQuery入门指引
2015/07/28 Javascript
JavaScript评论点赞功能的实现方法
2017/03/13 Javascript
微信小程序 动态绑定数据及动态事件处理
2017/03/14 Javascript
AngularJS 霸道的过滤器小结
2017/04/26 Javascript
JS设置手机验证码60s等待实现代码
2017/06/14 Javascript
JavaScript 值类型和引用类型的初次研究(推荐)
2017/07/19 Javascript
本地搭建微信小程序服务器的实现方法
2017/10/27 Javascript
ztree实现左边动态生成树右边为内容详情功能
2017/11/03 Javascript
Vue2.0设置全局样式(less/sass和css)
2017/11/18 Javascript
javaScript动态添加Li元素的实例
2018/02/24 Javascript
[02:40]DOTA2英雄基础教程 先知
2013/11/29 DOTA
[04:21]狐狸妈带你到现场 DOTA2 TI中国区预选赛线下赛路线指引
2014/05/22 DOTA
Python3 入门教程 简单但比较不错
2009/11/29 Python
一个简单的python程序实例(通讯录)
2013/11/29 Python
用Python和MD5实现网站挂马检测程序
2014/03/13 Python
Flask实现图片的上传、下载及展示示例代码
2018/08/03 Python
python发送多人邮件没有展示收件人问题的解决方法
2019/06/21 Python
Python更新所有已安装包的操作
2020/02/13 Python
PyCharm 在Windows的有用快捷键详解
2020/04/07 Python
如何基于python对接钉钉并获取access_token
2020/04/21 Python
python合并多个excel文件的示例
2020/09/23 Python
CSS Grid布局教程之什么是网格布局
2014/12/30 HTML / CSS
2分钟教你实现环形/扇形菜单(基础版)
2020/01/15 HTML / CSS
澳大利亚最早和最古老的巨型游戏专家:Yardgames
2020/02/20 全球购物
法人代表授权委托书
2014/04/08 职场文书
2014年党务公开工作总结
2014/12/09 职场文书
2014年会计主管工作总结
2014/12/20 职场文书
电信营业员岗位职责
2015/04/14 职场文书
上班迟到检讨书范文
2015/05/06 职场文书
地道战观后感2000字
2015/06/04 职场文书