javascript - 为什么不相关的元素会触发此点击事件?

标签 javascript reactjs event-handling

我正在开发这个工具提示,如果您将鼠标悬停在它上面,它会显示一个工具提示:

但是如果您(用手指)点击它,它将显示全屏(用于移动支持):

代码如下所示:

export default function Tooltip({ message, children }: Props) {
    const [showSmallTip, setShowSmallTip] = useState(false);
    const [showBigTap, setShowBigTip] = useState(false);
    const ref = useRef(null);
    const pos = useBoundingBox(ref);

    const handleMouseEnter = useCallback(() => {
        setShowSmallTip(true);
    }, [setShowSmallTip]);

    const handleMouseLeave = useCallback(() => {
        setShowSmallTip(false);
    }, [setShowSmallTip]);

    const handleTap = useCallback(() => {
        console.log("TAP!")
        setShowBigTip(true);
        setShowSmallTip(false);
    }, [setShowBigTip]);

    const closeFullscreen = useCallback((ev:MouseEvent<HTMLElement>) => {
        console.log('CLOSE!!!')
        ev.stopPropagation();
        setShowBigTip(false);
        setShowSmallTip(false);
    }, [setShowBigTip]);

    const onTap = useTap(handleTap);

    return <>
        <Wrapper ref={ref} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} {...onTap}>
            {children}
        </Wrapper>
        {showSmallTip ? <End container={SCROLL_ROOT}><StyledTooltip style={{ top: pos.bottom, left: (pos.left + pos.right) / 2 }}>{message}</StyledTooltip></End> : null}
        {showBigTap ? <End><FullscreenTip onClick={closeFullscreen}><FullscreenText>{message}</FullscreenText></FullscreenTip></End>:null}
    </>
}

哪里useTap是:

export default function useTap<T = Element>(callback: VoidCallback, options?: Options): TouchEvents<T> {
    const data = useRef<TouchData>(Object.create(null));

    return useMemo<TouchEvents<T>>(() => {
        const opt = { ...DEFAULT_OPTIONS, ...options } as Required<Options>;

        return {
            onTouchStart(ev) {
                data.current = {
                    time: ev.timeStamp,
                    x: ev.changedTouches[0].screenX,
                    y: ev.changedTouches[0].screenY,
                }
            },
            onTouchEnd(ev) {
                const mx = ev.changedTouches[0].screenX - data.current.x;
                const my = ev.changedTouches[0].screenY - data.current.y;
                const moved = Math.sqrt(mx**2 + my**2);
                const elapsed = ev.timeStamp - data.current.time;
                if (moved < opt.moveThreshold && elapsed < opt.pressDelay) {
                    // setTimeout(() => {
                        callback();
                    // }, 0);
                }
            }
        }
    }, [callback, options])
}

我遇到的问题是,当您点击它打开的图标并立即关闭全屏工具提示时。即,它打印

TAP!
CLOSE!!!

只需轻轻一按。

现在我知道了touchend click之前发生火灾,但我不明白为什么这很重要?如果你看看我的 {...onTap} 的位置和onClick={closeFullscreen}管理员,他们是 sibling 。事件不应该以这种方式冒泡(无论是在 native DOM 中还是 React's VDOM ),而且我当然没有单击 <FullscreenTip> 。那么到底怎么样closeFullscreen开火?

<End>是一个门户。

最佳答案

DEMO

尝试在 onTouchEnd 上调用 ev.preventDefault()

根据spec touchend 事件是“可取消”,这意味着您可以使用 .preventDefault() 来阻止鼠标事件。

If the preventDefault method is called on this event, it should prevent any default actions caused by any touch events associated with the same active touch point, including mouse events or scrolling.

enter image description here

关于javascript - 为什么不相关的元素会触发此点击事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60698406/

相关文章:

JavaScript querySelectorAll() 仍然会发现已被删除的 DOM 元素

javascript - 如何在页面第一次加载时打开 Popper

c++ - 用另一个函数替换 WndProc 来处理消息?

javascript - 异步 Promise 在执行之前存储在 JavaScript 中的哪里?

reactjs - 错误 TS2604 : JSX element type '...' does not have any construct or call signatures

javascript - 将当前元素作为参数传递给循环内的回调函数

javascript - 如何将非常大的 CSV 数据集加载到 d3

javascript - 为什么 console.log(true, '\t' ) 打印 true " "?

javascript - 如何基于 Rx.ReplaySubject 模型在 React 中设置初始状态

reactjs - 单击通知时 react native 导航到特定屏幕