MDC 菜单 - select 随机工作的事件侦听器

MDC Menu - select event listener working randomly

我有一个 MDC 菜单组件,我想在其中为列表项设置点击或 select 事件侦听器。我尝试过各种事件,例如 'click'、'select'、'selectionchange'、'selectstart',但其中 none 有效。在 documentation 它说 MDCMenu:selected

Used to indicate when an element has been selected. This event also includes the item selected and the list index of that item.

我也试过听那个事件,但没有任何效果:

menu.listen("MDCMenu:selected", e => console.log(e));

您可以看到沙盒here。 应该如何为 MDC 菜单组件设置事件侦听器?

更新

自从我在评论中得知该代码对其他用户来说确实有效之后。我自己用其他浏览器对其进行了测试,在 safari 和 firefox 中它在我的 mac machine 上运行良好,但在 Chrome 中我仍然有问题。我有 chrome 版本 83.0.4103.61。我已经根据评论中的建议更新了 codesandbox,但我现在可以看到,如果按几次 select 选项,它会突然在所有浏览器中随机开始工作。

不一致似乎是由竞争条件引起的。单击菜单会使焦点离开导致菜单关闭的输入。并且菜单关闭导致焦点移回输入使其再次打开。

问题是菜单经常在菜单有机会发出所选事件之前关闭。

您需要阻止菜单在 focusout 时关闭,或者在关闭菜单前设置一个宽大的超时时间。

input.listen("focusout", () => {
  setTimeout(() => {
    menu.open = false;
    // The timer might need to be fiddled with. Needs to not be too big or too small.
  }, 120);
});

https://codesandbox.io/s/new-brook-o7k1j?file=/src/index.js


这是另一个没有 setTimeout 计时问题的选项。它使用 0 的超时来模仿 setInterval,以便通过将事件推到事件队列的末尾来重新排序事件的时间。这应该更安全,更不容易出现之前的竞争条件问题。

let menuFocused = false;
input.listen("focusin", () => {
  if (!menuFocused) menu.open = true;
});
input.listen("click", () => {
  menu.open = true;
});

menu.listen("focusin", () => {
  menuFocused = true;
});
menu.listen("focusout", () => {
  // This interval is to help make sure that input.focusIn doesn't re-open the menu
  setTimeout(() => {
    menuFocused = false;
  }, 0);
});
input.listen("focusout", () => {
  setTimeout(() => {
    if (!menuFocused) menu.open = false;
  }, 0);
});

https://codesandbox.io/s/proud-hooks-c9qi5?file=/src/index.js