乐闻世界logo
搜索文章和话题

React 如何监听组件外部的点击事件?

2个答案

1
2

在React中,检测组件外部的点击事件通常可以通过以下几个步骤进行:

  1. 添加全局事件监听器:在组件挂载(componentDidMount 或者 useEffect)后,添加一个点击事件监听器到document上,这样可以监听到所有的点击事件。

  2. 设置引用(Ref):使用useRef创建一个引用,并将其附加到你希望检测外部点击的组件上。这允许我们可以访问真实的DOM节点,以判断点击事件是否发生在其内部。

  3. 检测点击位置:当全局点击事件被触发时,可以使用该事件的target属性,并与我们的组件的DOM节点进行比较,来确定点击是否在组件外部进行。

  4. 清理事件监听器:在组件卸载(componentWillUnmount 或者 useEffect的返回函数)时,要移除事件监听器,避免内存泄漏。

下面是一个使用Hooks实现的例子:

jsx
import React, { useEffect, useRef } from 'react'; function OutsideClickExample() { const wrapperRef = useRef(null); // Step 2 useEffect(() => { // Step 1 function handleClickOutside(event) { if (wrapperRef.current && !wrapperRef.current.contains(event.target)) { // Step 3 console.log('你点击了组件外部'); } } // 在document上添加事件监听器 document.addEventListener('mousedown', handleClickOutside); // Step 4 return () => { // 在组件卸载时移除事件监听器 document.removeEventListener('mousedown', handleClickOutside); }; }, [wrapperRef]); return ( <div ref={wrapperRef}> <p>点击我之外的地方试试看!</p> </div> ); } export default OutsideClickExample;

在这个例子中,useEffect确保了事件监听器仅在组件挂载后添加,并在组件卸载时移除。ref的作用是提供了一种方式来引用实际的DOM元素,从而我们可以判断点击事件是否在这个元素之外发生。注意,这个例子使用了mousedown事件,它会在点击鼠标按钮时立即触发,而不是在释放按钮时(click事件)。根据你的应用场景,你可能需要选择不同的事件类型。

2024年6月29日 12:07 回复

以下解决方案使用 ES6 并遵循绑定的最佳实践以及通过方法设置引用。

要查看它的实际效果:

钩子实现:

shell
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 <div ref={wrapperRef}>{props.children}</div>; }

类实现:

16.3之后

shell
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 <div ref={this.wrapperRef}>{this.props.children}</div>; } }

16.3之前

shell
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 <div ref={this.setWrapperRef}>{this.props.children}</div>; } }
2024年6月29日 12:07 回复

你的答案