首页 > 解决方案 > React - 如果事件是从此组件当前呈现的元素触发的,则不要调用方法

问题描述

我目前有这个代码

import { Tooltip } from "Toolkit";
import React, { Component } from "react";

export default class TooltipWrapper extends Component {
    constructor() {
        super();

        this.handleWindowClick = this.handleWindowClick.bind(this);
        this.toggleTooltip = this.toggleTooltip.bind(this);
        this.onTooltipClosed = this.onTooltipClosed.bind(this);
    }

    state = {
        show: false,
    };

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

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

    onTooltipClosed() {
        this.setState({
            show: false,
        });
    }

    handleWindowClick(event) {
        if (this.state.show) {
            this.setState({
                show: false,
            });
        }
    }

    toggleTooltip(event) {
        this.setState({
            show: !this.state.show,
        });
    }

    render() {
        return (
            <Tooltip
                open={this.state.show}
                tip={this.props.tip}
                onClose={this.onTooltipClosed}
                {...this.props}
            >
                <div onClick={this.toggleTooltip}>{this.props.children}</div>
            </Tooltip>
        );
    }
}

我遇到了handleWindowClick之前调用该函数的问题toggleTooltip。结果,每当我单击工具提示将其关闭时,handleWindowClick总是首先将状态设置为 false,然后toggleTooltip再次打开它。

当我在工具提示之外单击以关闭它时,该handleWindowClick功能按预期工作,当我单击另一个工具提示时,它也会关闭。

在 handleWindowClick 中,我认为解决方案是,如果我单击了当前在该实例中呈现的工具提示中的任何位置,我不想做任何事情。关于如何做到这一点的任何想法?

谢谢

标签: javascriptreactjs

解决方案


TLDR:

handleWindowClick(event) {
    if (event.handledByTooltip !== this && this.state.show) {
        this.setState({
            show: false,
        });
    }
}

toggleTooltip(event) {
    event.handledByTooltip = this;
    this.setState({
        show: !this.state.show,
    });
}

由于事件在 DOM 层次结构中冒泡的方式,toggleTooltip应该称为 bofore handleWindowClick。在每个函数中,您都可以检查事件以确定要采取的操作。

事件的有用属性之一是target对实际单击的元素的引用。不幸的是,这通常是 element 的子元素之一,而不是我们真正关心的元素,因此if (event.target === myToolTipElement)通常不起作用。您将需要查看父级event.target和该父级等等。

您可以使用event.stopPropagation()来阻止事件冒泡高于工具提示,但这只能作为最后的手段,因为大多数事件通常会一直冒泡到顶部,其他代码可能依赖于此。

如果您event.preventDefault()在工具提示处理程序中调用,那么event.defaultPrevented在窗口处理程序中将是真的。太好了,您可以从工具提示处理程序与窗口处理程序进行通信!但是preventDefault用于与浏览器通信,您已经处理了该事件并且它不应该做它打算做的事情,所以这也不太适合这个问题。

传达工具提示处理程序已经看到事件的想法是一个很好的想法,但您还需要知道哪个工具提示处理了事件。因此,toggleTooltip您可以使用event一些标识处理它的工具提示的值(我使用this的是工具提示独有的)来注释 ,并且handleWindowClick您可以比较这些值以查看工具提示是否已经处理了该事件。这样,如果您单击一个工具提示,handleWindowClick来自任何其他处理程序的仍然可以完成它的工作。


推荐阅读