需要模拟一个点击事件,但在这种情况下非常困难,因为代码很复杂。

16 浏览
0 Comments

需要模拟一个点击事件,但在这种情况下非常困难,因为代码很复杂。

我正在寻找一种方法,以检测点击事件是否发生在组件之外,就像这篇 文章 中所描述的那样。使用 jQuery 的 closest() 方法来查看点击事件的目标是否具有该元素作为其父元素之一。 如果存在匹配项,则点击事件属于其中一个子节点,因此不被认为是在组件之外。

因此,在我的组件中,我想将点击处理程序附加到 window。 当处理程序触发时,我需要将目标与我的组件的 DOM 子节点进行比较。

点击事件包含像“路径”这样的属性,它似乎保存了事件所经过的 DOM 路径。我不确定要比较什么或如何最好地遍历它,我认为有人一定已经将其放在聪明的实用程序函数中了……对不对?

admin 更改状态以发布 2023年5月22日
0
0 Comments

我曾经遇到过同样的问题。我有些晚来到这里,但对我而言,这是一个非常好的解决方案。希望它对其他人有所帮助。你需要从react-dom中导入findDOMNode

import ReactDOM from 'react-dom';
// ... 
componentDidMount() {
    document.addEventListener('click', this.handleClickOutside, true);
}
componentWillUnmount() {
    document.removeEventListener('click', this.handleClickOutside, true);
}
handleClickOutside = event => {
    const domNode = ReactDOM.findDOMNode(this);
    if (!domNode || !domNode.contains(event.target)) {
        this.setState({
            visible: false
        });
    }
}


React Hooks方法(16.8 +)

你可以创建一个可重复使用的Hook,名为useComponentVisible

import { useState, useEffect, useRef } from 'react';
export default function useComponentVisible(initialIsVisible) {
    const [isComponentVisible, setIsComponentVisible] = useState(initialIsVisible);
    const ref = useRef(null);
    const handleClickOutside = (event) => {
        if (ref.current && !ref.current.contains(event.target)) {
            setIsComponentVisible(false);
        }
    };
    useEffect(() => {
        document.addEventListener('click', handleClickOutside, true);
        return () => {
            document.removeEventListener('click', handleClickOutside, true);
        };
    }, []);
    return { ref, isComponentVisible, setIsComponentVisible };
}

然后在你希望添加该功能的组件中进行以下操作:

const DropDown = () => {
    const { ref, isComponentVisible } = useComponentVisible(true);
    return (
          {isComponentVisible && (

Dropdown Component

)} ); }

在此处可以找到codesandbox示例。

0
0 Comments

下面的解决方案使用ES6并遵循最佳实践,包括通过方法绑定和设置引用。

在代码中查看实现:

Hooks实现:

import React, { useRef, useEffect } from "react";
/**
 * Hook that alerts clicks outside of the passed ref
 */
function useOutsideAlerter(ref) {
  useEffect(() => {
    /**
     * Alert if clicked on outside of element
     */
    function handleClickOutside(event) {
      if (ref.current && !ref.current.contains(event.target)) {
        alert("You clicked outside of me!");
      }
    }
    // Bind the event listener
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [ref]);
}
/**
 * Component that alerts if you click outside of it
 */
export default function OutsideAlerter(props) {
  const wrapperRef = useRef(null);
  useOutsideAlerter(wrapperRef);
  return {props.children};
}

Class实现:

16.3版本后

import React, { Component } from "react";
/**
 * Component that alerts if you click outside of it
 */
export default class OutsideAlerter extends Component {
  constructor(props) {
    super(props);
    this.wrapperRef = React.createRef();
    this.handleClickOutside = this.handleClickOutside.bind(this);
  }
  componentDidMount() {
    document.addEventListener("mousedown", this.handleClickOutside);
  }
  componentWillUnmount() {
    document.removeEventListener("mousedown", this.handleClickOutside);
  }
  /**
   * Alert if clicked on outside of element
   */
  handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.current.contains(event.target)) {
      alert("You clicked outside of me!");
    }
  }
  render() {
    return {this.props.children};
  }
}

16.3版本前

import React, { Component } from "react";
/**
 * Component that alerts if you click outside of it
 */
export default class OutsideAlerter extends Component {
  constructor(props) {
    super(props);
    this.setWrapperRef = this.setWrapperRef.bind(this);
    this.handleClickOutside = this.handleClickOutside.bind(this);
  }
  componentDidMount() {
    document.addEventListener("mousedown", this.handleClickOutside);
  }
  componentWillUnmount() {
    document.removeEventListener("mousedown", this.handleClickOutside);
  }
  /**
   * Set the wrapper ref
   */
  setWrapperRef(node) {
    this.wrapperRef = node;
  }
  /**
   * Alert if clicked on outside of element
   */
  handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      alert("You clicked outside of me!");
    }
  }
  render() {
    return {this.props.children};
  }
}

0