博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
检测React组件外部的点击
阅读量:3581 次
发布时间:2019-05-20

本文共 6920 字,大约阅读时间需要 23 分钟。

本文翻译自:

I'm looking for a way to detect if a click event happened outside of a component, as described in this . 我正在寻找一种检测点击事件是否在组件外部发生的方法,如 。 jQuery closest() is used to see if the the target from a click event has the dom element as one of its parents. jQuery最近的()用于查看单击事件中的目标是否将dom元素作为其父元素之一。 If there is a match the click event belongs to one of the children and is thus not considered to be outside of the component. 如果存在匹配项,则click事件属于子项之一,因此不被视为在组件外部。

So in my component I want to attach a click handler to window. 因此,在我的组件中,我想将单击处理程序附加到窗口。 When the handler fires I need to compare the target with the dom children of my component. 处理程序触发时,我需要将目标与组件的dom子代进行比较。

The click event contains properties like "path" which seems to hold the dom path that the event has travelled. click事件包含“ path”之类的属性,该属性似乎包含事件经过的dom路径。 I'm not sure what to compare or how to best traverse it, and I'm thinking someone must have already put that in a clever utility function... No? 我不确定要比较什么或如何最好地遍历它,并且我认为有人必须已经将其放在聪明的实用程序函数中了……不?


#1楼

参考:


#2楼

You could just install a double click handler on the body and another one on this element. 您可以只在主体上安装一个双击处理程序,然后在此元素上安装另一个。 In the handler of this element just return false to prevent the event from propagating. 在此元素的处理程序中,只需返回false即可防止事件传播。 So when a double click happens if it is on the element it will be caught and will not propagate to the handler on the body. 因此,如果双击发生在元素上,它将被捕获并且不会传播到主体上的处理程序。 Otherwise it will be caught by the handler on the body. 否则它将被身体上的处理者抓住。

Update: if you really do not want to prevent event propagation, you just need to use closest to check whether the click happened on your element or one of his children: 更新:如果您确实不想阻止事件传播,则只需使用最接近值来检查单击是否发生在元素上或其元素之一上:

    

Update: without jQuery: 更新:没有jQuery:

    

#3楼

I found a solution thanks to Ben Alpert on . 我感谢Ben Alpert在上找到了解决方案。 The suggested approach attaches a handler to the document but that turned out to be problematic. 建议的方法将处理程序附加到文档,但是事实证明这是有问题的。 Clicking on one of the components in my tree resulted in a rerender which removed the clicked element on update. 单击树中的一个组件会导致重新渲染,从而删除了更新时单击的元素。 Because the rerender from React happens before the document body handler is called, the element was not detected as "inside" the tree. 由于从React重新渲染发生调用文档主体处理程序之前 ,因此未在树“内部”检测到该元素。

The solution to this was to add the handler on the application root element. 解决方案是在应用程序根元素上添加处理程序。

main: 主要:

window.__myapp_container = document.getElementById('app')React.render(
, window.__myapp_container)

component: 零件:

import { Component, PropTypes } from 'react';import ReactDOM from 'react-dom';export default class ClickListener extends Component {  static propTypes = {    children: PropTypes.node.isRequired,    onClickOutside: PropTypes.func.isRequired  }  componentDidMount () {    window.__myapp_container.addEventListener('click', this.handleDocumentClick)  }  componentWillUnmount () {    window.__myapp_container.removeEventListener('click', this.handleDocumentClick)  }  /* using fat arrow to bind to instance */  handleDocumentClick = (evt) => {    const area = ReactDOM.findDOMNode(this.refs.area);    if (!area.contains(evt.target)) {      this.props.onClickOutside(evt)    }  }  render () {    return (      
{this.props.children}
) }}

#4楼

Here is the solution that best worked for me without attaching events to the container: 这是最适合我的解决方案,无需将事件附加到容器:

Certain HTML elements can have what is known as " focus ", for example input elements. 某些HTML元素可以具有所谓的“ 焦点 ”,例如输入元素。 Those elements will also respond to the blur event, when they lose that focus. 当这些元素失去焦点时,它们也会响应模糊事件。

To give any element the capacity to have focus, just make sure its tabindex attribute is set to anything other than -1. 要使任何元素都有焦点的能力,只需确保其tabindex属性设置为-1以外的任何值即可。 In regular HTML that would be by setting the tabindex attribute, but in React you have to use tabIndex (note the capital I). 在常规HTML中,可以通过设置tabindex属性来实现,但是在React中,您必须使用tabIndex(请注意大写的I)。

You can also do it via JavaScript with element.setAttribute('tabindex',0) 您也可以通过JavaScript使用element.setAttribute('tabindex',0)

This is what I was using it for, to make a custom DropDown menu. 这就是我用来制作自定义DropDown菜单的目的。

var DropDownMenu = React.createClass({    getInitialState: function(){        return {            expanded: false        }    },    expand: function(){        this.setState({expanded: true});    },    collapse: function(){        this.setState({expanded: false});    },    render: function(){        if(this.state.expanded){            var dropdown = ...; //the dropdown content        } else {            var dropdown = undefined;        }        return (            
{this.props.displayValue}
{dropdown}
); }});

#5楼

After trying many methods here, I decided to use because of how complete it is. 在尝试了许多方法之后,由于它的完整性,我决定使用 。

I installed the module via npm and imported it into my component: 我通过npm安装了模块,并将其导入到我的组件中:

import onClickOutside from 'react-onclickoutside'

Then, in my component class I defined the handleClickOutside method: 然后,在我的组件类中,我定义了handleClickOutside方法:

handleClickOutside = () => {  console.log('onClickOutside() method called')}

And when exporting my component I wrapped it in onClickOutside() : 导出组件时,我将其包装在onClickOutside()

export default onClickOutside(NameOfComponent)

That's it. 而已。


#6楼

Here is my approach (demo - ): 这是我的方法(演示-https: ):

I've created special component called WatchClickOutside and it can be used like (I assume JSX syntax): 我创建了一个名为WatchClickOutside特殊组件,它的使用方式类似于(假设JSX语法):

Here is code of WatchClickOutside component: 这是WatchClickOutside组件的代码:

import React, { Component } from 'react';export default class WatchClickOutside extends Component {  constructor(props) {    super(props);    this.handleClick = this.handleClick.bind(this);  }  componentWillMount() {    document.body.addEventListener('click', this.handleClick);  }  componentWillUnmount() {    // remember to remove all events to avoid memory leaks    document.body.removeEventListener('click', this.handleClick);  }  handleClick(event) {    const {container} = this.refs; // get container that we'll wait to be clicked outside    const {onClickOutside} = this.props; // get click outside callback    const {target} = event; // get direct click event target    // if there is no proper callback - no point of checking    if (typeof onClickOutside !== 'function') {      return;    }    // if target is container - container was not clicked outside    // if container contains clicked target - click was not outside of it    if (target !== container && !container.contains(target)) {      onClickOutside(event); // clicked outside - fire callback    }  }  render() {    return (      
{this.props.children}
); }}

转载地址:http://tmlgj.baihongyu.com/

你可能感兴趣的文章
Java JSON字符串与自定义类/基本类型相互转换
查看>>
Java中时间戳和时间格式的转换
查看>>
Dubbo基础知识整理
查看>>
计算机网络知识整理
查看>>
Java基础知识
查看>>
操作系统知识整理
查看>>
实现自己的权限管理系统(二):环境配置以及遇到的坑
查看>>
实现自己的权限管理系统(四): 异常处理
查看>>
实现自己的权限管理系统(十):角色模块
查看>>
实现自己的权限管理系统(十二):权限操作记录
查看>>
实现自己的权限管理系统(十三):redis做缓存
查看>>
实现自己的权限管理系统(十四):工具类
查看>>
JavaWeb面经(二):2019.9.16 Synchronized关键字底层原理及作用
查看>>
牛客的AI模拟面试(1)
查看>>
深入浅出MyBatis:MyBatis解析和运行原理
查看>>
Mybatis与Ibatis
查看>>
字节码文件(Class文件)
查看>>
java中的IO流(一)----概述
查看>>
StringBuilder
查看>>
集合,Collection
查看>>