You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端onClick事件异常求助:游戏网格选中与背景切换异常

问题分析

移动端触摸操作会模拟鼠标事件:点击网格时会触发onMouseEnter,但触摸结束后不会自动触发onMouseLeave(除非触摸离开该元素),导致beingHovered状态一直为true。当再次点击取消选中时,beingHovered || selected的结果仍为true,所以背景无法恢复;而点击其他网格时,当前网格的onMouseLeave会被触发,beingHovered重置为false,背景才正常恢复。

解决方案

方案1:使用Pointer事件替代鼠标事件

Pointer事件是W3C标准,同时兼容鼠标和触摸操作,能自动处理触摸后的状态重置:

function Grid(): JSX.Element {
    const myRef = useRef<HTMLDivElement>(null);
    const [beingHovered, setBeingHovered] = useState(false);
    const [selected, setSelected] = useState(false);
    const hoverStyle = {
        backgroundImage: "url(/assets/stamp.png)",
        backgroundSize: "contain",
        backgroundRepeat: "no-repeat"
    };
    const background = (beingHovered || selected) ? hoverStyle : {};
    return (
        <div className="Grid"
             onPointerEnter={() => setBeingHovered(true)}
             onPointerLeave={() => setBeingHovered(false)}
             onClick={() => setSelected(!selected)}
             style={background}
             ref={myRef}
        >
            <span>The quick brown fox jumps over the lazy dog</span>
        </div>
    );
}

方案2:点击时手动重置hover状态

如果需要兼容不支持Pointer事件的环境,可在点击事件中强制重置beingHovered:

function Grid(): JSX.Element {
    const myRef = useRef<HTMLDivElement>(null);
    const [beingHovered, setBeingHovered] = useState(false);
    const [selected, setSelected] = useState(false);
    const hoverStyle = {
        backgroundImage: "url(/assets/stamp.png)",
        backgroundSize: "contain",
        backgroundRepeat: "no-repeat"
    };
    const background = (beingHovered || selected) ? hoverStyle : {};
    
    const handleClick = () => {
        setSelected(!selected);
        setBeingHovered(false);
    };

    return (
        <div className="Grid"
             onMouseEnter={() => setBeingHovered(true)}
             onMouseLeave={() => setBeingHovered(false)}
             onClick={handleClick}
             style={background}
             ref={myRef}
        >
            <span>The quick brown fox jumps over the lazy dog</span>
        </div>
    );
}

方案3:用CSS媒体查询分离桌面/移动端效果

将hover样式移到CSS中,仅在桌面端生效,彻底避免触摸事件冲突:

.Grid {
  /* 基础样式 */
}

/* 仅在支持精确指针的设备(桌面端)显示hover效果 */
@media (hover: hover) and (pointer: fine) {
  .Grid:hover {
    background-image: url(/assets/stamp.png);
    background-size: contain;
    background-repeat: no-repeat;
  }
}

组件代码简化为:

function Grid(): JSX.Element {
    const myRef = useRef<HTMLDivElement>(null);
    const [selected, setSelected] = useState(false);
    const selectedStyle = {
        backgroundImage: "url(/assets/stamp.png)",
        backgroundSize: "contain",
        backgroundRepeat: "no-repeat"
    };

    return (
        <div className="Grid"
             onClick={() => setSelected(!selected)}
             style={selected ? selectedStyle : {}}
             ref={myRef}
        >
            <span>The quick brown fox jumps over the lazy dog</span>
        </div>
    );
}

内容的提问来源于stack exchange,提问作者Nahid Islam Shaiket

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:10:54