コンポーネント外でクリックイベントが発生したかどうかを検出する方法を探しています。記事jQuery のclosest() は、クリック イベントのターゲットにその親の 1 つとして dom 要素があるかどうかを確認するために使用されます。一致する場合、クリック イベントは子の 1 つに属しているため、コンポーネントの外部にあるとは見なされません。
そこで、コンポーネントで、クリック ハンドラーを にアタッチしますwindow
。ハンドラーが起動したら、ターゲットをコンポーネントの dom の子と比較する必要があります。
クリック イベントには、イベントが移動した DOM パスを保持していると思われる「path」などのプロパティが含まれています。何を比較するか、またはどのようにトラバースするのが最適かはわかりませんが、誰かがすでにそれを巧妙なユーティリティ関数に組み込んでいるに違いないと思っています... 違いますか?
ベストアンサー1
次のソリューションは ES6 を使用し、メソッドを通じて ref を設定するだけでなく、バインディングに関するベスト プラクティスに従います。
実際に動作する様子を見るには:
フックの実装:
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以降
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以前
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>;
}
}