如何在 svelte 中向 window 事件/鼠标滚轮添加参数

How to add parameters to a window event / mouse wheel in svelte

我想听鼠标滚轮的声音,如果鼠标位于某个元素上方,则取消默认设置并改为执行我的操作。

现在我只想记录事件并阻止它:

  const handleWheel = e => {
    console.log(e);
    e.preventDefault();
  };

使用 svelte 这就是我想到的:

<svelte:window on:wheel={handleWheel} />

不幸的是,这只会让我记录事件,并给出此错误消息:

Unable to preventDefault inside passive event listener invocation.

使用纯JS解决办法是加一个参数:

window.addEventListener("wheel", handleWheel, { passive: false});

但我在提及如何完成此操作的 svelte 文档中找不到任何方法。那么你将如何以苗条的方式做到这一点?

好吧,你的代码对我来说确实有效...

<script>
  const handleWheel = e => {
    console.log(e);
    e.preventDefault();
  };
</script>

<svelte:window on:wheel={handleWheel} />

参见 in the REPL

可能是您的浏览器问题,但我想也可能是 REPL 本身(如果您使用的是它)<svelte:window /> 事件可能存在一些问题,并显示过时的日志...

实际上,您的解决方案会做与您想要的相反的事情,并导致警告:

window.addEventListener("wheel", handleWheel, { passive: true });

来自 MDN:

passive

A Boolean which, if true, indicates that the function specified by listener will never call preventDefault(). If a passive listener does call preventDefault(), the user agent will do nothing other than generate a console warning.

除此之外,Svelte 向事件侦听器添加选项的方法是使用 修饰符

例如:

<svelte:window on:wheel|preventDefault={handleWheel} />

<svelte:window on:wheel|passive={handleWheel} />

它们可以组合,但是 preventDefaultpassive 不能很好地组合在一起,所以让我们使用另一个:

<svelte:window on:wheel|preventDefault|once={handleWheel} />

有关可用修饰符和详细信息,请参阅 Svelte 的 docs on events

The following modifiers are available:

preventDefault — calls event.preventDefault() before running the handler

stopPropagation — calls event.stopPropagation(), preventing the event reaching the next element

passive — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)

capture — fires the handler during the capture phase instead of the bubbling phase

once — remove the handler after the first time it runs

Modifiers can be chained together, e.g. on:click|once|capture={...}.

目前,无法使用事件处理程序以惯用的方式执行此操作,因为 Chrome broke the web by making certain event listeners passive by default. There's an open Svelte issue 可以解决此问题。

同时,最惯用的方法可能是使用一个动作:

<script>
  let scrollable = true;

  const wheel = (node, options) => {
    let { scrollable } = options;

    const handler = e => {
      if (!scrollable) e.preventDefault();
    };

    node.addEventListener('wheel', handler, { passive: false });

    return {
      update(options) {
        scrollable = options.scrollable;
      },
      destroy() {
        node.removeEventListener('wheel', handler, { passive: false });
      }
    };
  };
</script>

<svelte:window use:wheel={{scrollable}} />

Demo here.