为什么React的onContextMenu在Chrome中对禁用的元素起作用?

huangapple go评论116阅读模式
英文:

Why does React's onContextMenu work in Chrome on disabled elements?

问题

我发现了一些非常奇怪的事情。在所有主要的浏览器中,上下文菜单事件在禁用的元素上不起作用,所以这不会在控制台中打印出来:

<button
    type="button"
    onContextMenu={() => console.log(123)}
    disabled
>
    点我
</button>

但是在 React 中有点不同。我试图通过 React 组件来做同样的事情:

const MyComponent = () => (
    <button
        type="button"
        onContextMenu={() => console.log(123)}
        disabled
    >
        点我
    </button>
);

这一次,在 Chrome 中会在控制台中打印,但在其他浏览器中不会。出于教育目的,我试图理解 HTML 的 onContextMenu 和 React 的 onContextMenu 之间的区别,以及为什么只有 Chrome 处理它不同。非常奇怪。

Codesandbox 中重现。

英文:

I found something very strange. In all major browsers, context menu event doesn't work on disabled elements, so this wouldn't print to console:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;button
    type=&quot;button&quot;
    onContextMenu=&quot;console.log(123)&quot;
    disabled
&gt;
    Click me
&lt;/button&gt;

<!-- end snippet -->

But it's a little different with React. I tried to do the same thing through React component:

const MyComponent = () =&gt; (
    &lt;button
        type=&quot;button&quot;
        onContextMenu={() =&gt; console.log(123)}
        disabled
    &gt;
        Click me
    &lt;/button&gt;
);

This time, in Chrome it prints to the console, but in other browsers it does not. For educational purpose, I'm trying to understand what is the difference between HTML's onContextMenu and React's onContextMenu plus why only Chrome handles it differently. Super weird.

Reproduced in Codesandbox

答案1

得分: 1

我花了一段时间研究这个问题。似乎这是Chrome中的一个 bug,即使contextmenuPointerEvent的一种类型,在冒泡时仍然会触发在禁用的元素上。

这里有一个没有使用React的JSFiddle:https://jsfiddle.net/bpe0yoc6/4/

React在DOM树的根部注册事件处理程序,这就是为什么这样做不起作用的原因:

document.querySelector("button").addEventListener("contextmenu", (e) => { ... })

不会在禁用的按钮上触发,oncontextmenu也一样。

我在Chromium问题跟踪器上提出了一个问题:https://bugs.chromium.org/p/chromium/issues/detail?id=1421370

英文:

I spent a while digging into this. It seems like a bug in Chrome where contextmenu, despite being a type of PointerEvent, fires on disabled elements but only when bubbling.

Here's a JSFiddle without React: https://jsfiddle.net/bpe0yoc6/4/

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

// Only in chrome does this fire
document.querySelector(&quot;#root&quot;).addEventListener(&quot;contextmenu&quot;, (e) =&gt; { console.log(&quot;contextmenu fired&quot;, e.target.tagName) })

document.querySelector(&quot;#root&quot;).addEventListener(&quot;click&quot;, (e) =&gt; { console.log(&quot;click fired&quot;, e.target.tagName) })

<!-- language: lang-css -->

#root {
  width: 200px;
  height: 200px;
  display: block;
  background-color: #ccc;
}

<!-- language: lang-html -->

&lt;div id=&quot;root&quot;&gt;
  &lt;button
      type=&quot;button&quot;
      disabled
  &gt;
      Click me
  &lt;/button&gt;
&lt;/div&gt;

<!-- end snippet -->

React registers event handles at the root of the DOM tree, which is why doing this:

document.querySelector(&quot;button&quot;).addEventListener(&quot;contextmenu&quot;, (e) =&gt; { ... })

will not fire on the disabled button, and neither will oncontextmenu.

I opened an issue on the Chromium issue tracker: https://bugs.chromium.org/p/chromium/issues/detail?id=1421370

答案2

得分: 1

根据Chromium,这是故意的。请查看问题跟踪器

这是一个故意的更改,并与火狐夜间版实施的新行为相匹配。
由于其他问题,我暂时禁用了新的行为,但很快会重新启用。
禁用属性只应该阻止点击事件,而不是上下文菜单事件。你能在上下文菜单事件上调用preventDefault()吗?

听起来现在需要进行显式检查。

英文:

According to Chromium, this is intentional. See the issue tracker.

> This is an intentional change and matches what firefox nightly, who also implemented the new behavior, is doing.
> I have temporarily disabled the new behavior due to other issues, but I will re-enable it soon.
> The disabled attribute is only supposed to block click events, not contextmenu events. Can you just call preventDefault() on the contextmenu event?

Sounds like an explicit check is now required.

huangapple
  • 本文由 发表于 2023年3月4日 03:17:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631064.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定