React冒泡和阻止冒泡的应用详解


Posted in Javascript onAugust 18, 2020

阻止事件冒泡分三种:

1:阻止合成事件往最外层document上的事件冒泡,用e.nativeEvent.stopImmediatePropagation();

2: 合成事件间的冒泡,使用 e.stopPropagation();

3:阻止合成事件,往处理document上的其他原生事件冒泡,需要通过e.target来判断,示例代码如下。

import React,{ Component } from 'react';
import ReactDOM,{findDOMNode} from 'react-dom';

class Counter extends Component{
constructor(props){
super(props);

this.state = {
count:0,
    }
  }

handleClick(e){
this.setState({count:++this.state.count});
  }
render(){
return(
<div ref="test">
<p>{this.state.count}</p>
<a ref="update" onClick={(e)=>this.handleClick(e)}>更新</a>
</div>
    )
  }

componentDidMount() {
document.body.addEventListener('click',e=>{
// 通过e.target判断阻止冒泡
      if(e.target&&e.target.matches('a')){
return;
      }
console.log('body');
    })
  }
}

var div1 = document.getElementById('content');

ReactDOM.render(<Counter/>,div1,()=>{});

需求

最近在写react的项目,需要手写一个自定义的菜单,和antd的menu不同,需要点击一级菜单后弹出类似一个Drawer展示二级和三级菜单,且菜单样式自定义,都在一个Drawer里展示。

难点

其中难点在于点击一级菜单时弹出Drawer,点击除Drawer和一级菜单项之外的dom,Drawer收起。

问题

乍一想就是给document添加一个点击事件监听,给Drawer和一级菜单添加阻止冒泡,思路确实如此,后面实现中发现:
react为提高性能,有自己的一套事件处理机制,相当于将事件代理到全局进行处理,也就是说监听函数并未绑定到Dom上。 因此阻止react的事件冒泡e.stopPropagation(),就不发阻止原生事件的冒泡,表现为点击Drawer也会收起Drawer;禁用原生事件冒泡e.nativeEvent.stopPropagation(),React的监听函数就调用不到,表现为点击Drawer以外dom,Drawer不会收起。这些都不是我们想要的。

解决方案

正确的姿势应该是判断event.target对象是否是目标对象或包含目标对象或被包含目标对象,以此来决定是否触发事件

componentDidMount() {
  document.addEventListener('click', this.hideDrawer);
 }

 componentWillUnmount() {
  document.removeEventListener('click', this.hideDrawer);
 }

 hideDrawer = e => {
  const { closeDrawer } = this.props;
  // 找到不需要关闭的dom 一级菜单
  const tabContent = document.querySelectorAll('.ant-menu-submenu-vertical');
  // 找到不需要关闭的dom   Drawer
  const drawerContent = document.querySelector('#menuDrawer');
  // 判断当前点击的dom对象有没有包含在目标dom中
  const isHave = Array.from(tabContent).some(item => item.contains(e.target));
  // 不包含则关闭Drawer 包含就走其他的业务逻辑了
  if (tabContent !== null && !(isHave || drawerContent.contains(e.target))) {
   closeDrawer();
  }
 };

到此这篇关于React冒泡和阻止冒泡的应用详解的文章就介绍到这了,更多相关React冒泡和阻止冒泡内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木! 

Javascript 相关文章推荐
JavaScript 调试器简介
Feb 21 Javascript
JavaScript 题型问答有答案参考
Feb 17 Javascript
图片上传插件jquery.uploadify详解
Nov 15 Javascript
js数组去重的常用方法总结
Jan 24 Javascript
14款经典网页图片和文字特效的jQuery插件-前端开发必备
Aug 25 Javascript
浅析jQuery 遍历函数,javascript中的each遍历
May 25 Javascript
JavaScript编写带旋转+线条干扰的验证码脚本实例
May 30 Javascript
Bootstrap插件全集
Jul 18 Javascript
微信小程序 wxapp内容组件 icon详细介绍
Oct 31 Javascript
网页中的图片查看器viewjs使用方法
Jul 11 Javascript
详解如何实现一个简单的 vuex
Feb 10 Javascript
Vue3 源码导读(推荐)
Oct 14 Javascript
JavaScript数组排序的六种常见算法总结
Aug 18 #Javascript
js实现简单扫雷
Nov 27 #Javascript
基于JavaScript实现大文件上传后端代码实例
Aug 18 #Javascript
javascript实现扫雷简易版
Aug 18 #Javascript
详解Vue的组件中data选项为什么必须是函数
Aug 17 #Javascript
Openlayers实现扩散的动态点(水纹效果)
Aug 17 #Javascript
openLayer4实现动态改变标注图标
Aug 17 #Javascript
You might like
PHP设计聊天室步步通
2006/10/09 PHP
PHP安全的URL字符串base64编码和解码
2014/06/19 PHP
php常用的安全过滤函数集锦
2014/10/09 PHP
php实现上传图片文件代码
2015/07/19 PHP
PHP简单实现二维数组赋值与遍历功能示例
2017/10/19 PHP
JS版网站风格切换实例代码
2008/10/06 Javascript
十分钟打造AutoComplete自动完成效果代码
2009/12/26 Javascript
使用SyntaxHighlighter实现HTML高亮显示代码的方法
2010/02/04 Javascript
JavaScript版的TwoQueues缓存模型
2014/12/29 Javascript
jQuery实现根据类型自动显示和隐藏表单
2015/03/18 Javascript
JS实现可关闭的对联广告效果代码
2015/09/14 Javascript
js判断登陆用户名及密码是否为空的简单实例
2016/05/16 Javascript
前端程序员必须知道的高性能Javascript知识
2016/08/24 Javascript
微信小程序 获取当前地理位置和经纬度实例代码
2016/12/05 Javascript
jQuery模拟爆炸倒计时功能实例代码
2017/08/21 jQuery
微信小程序左右滑动的实现代码
2017/12/15 Javascript
vue文件树组件使用详解
2018/03/29 Javascript
详解处理bootstrap4不支持远程静态框问题
2018/07/20 Javascript
node.js爬取中关村的在线电瓶车信息
2018/11/13 Javascript
详解ECMAScript2019/ES10新属性
2019/12/06 Javascript
浅析Vue 中的 render 函数
2020/02/28 Javascript
[01:05:00]2018国际邀请赛 表演赛 Pain vs OpenAI
2018/08/24 DOTA
python实现将元祖转换成数组的方法
2015/05/04 Python
python中循环语句while用法实例
2015/05/16 Python
Python做简单的字符串匹配详解
2017/03/21 Python
Python学习思维导图(必看篇)
2017/06/26 Python
python 获取图片分辨率的方法
2019/01/08 Python
Python实现SQL注入检测插件实例代码
2019/02/02 Python
python tkinter实现界面切换的示例代码
2019/06/14 Python
如何解决django-celery启动后迅速关闭
2019/10/16 Python
Html5应用程序缓存(Cache manifest)
2018/06/04 HTML / CSS
Right-on官方网站:日本知名的休闲服装品牌
2019/07/12 全球购物
体育教育个人自荐信范文
2013/12/01 职场文书
就业意向书范文
2014/04/01 职场文书
护士个人年度总结范文
2015/02/13 职场文书
新郎接新娘保证书
2015/05/08 职场文书