admin管理员组

文章数量:1334852

I would like to listen to the mouse wheel, and if the mouse is position above a certain element, cancel the default and do my stuff instead.

For now I just want to log the event and prevent it:

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

Using svelte this is what I came up with:

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

Unfortantly this only lets me log the event, and gives this error message:

Unable to preventDefault inside passive event listener invocation.

Using pure JS the solution is to add a parameter:

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

But I can find no way in the svelte documentation that mentions how this can be done. So how would you do this the svelte way?

I would like to listen to the mouse wheel, and if the mouse is position above a certain element, cancel the default and do my stuff instead.

For now I just want to log the event and prevent it:

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

Using svelte this is what I came up with:

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

Unfortantly this only lets me log the event, and gives this error message:

Unable to preventDefault inside passive event listener invocation.

Using pure JS the solution is to add a parameter:

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

But I can find no way in the svelte documentation that mentions how this can be done. So how would you do this the svelte way?

Share Improve this question edited Feb 3, 2020 at 7:35 devzero asked Feb 2, 2020 at 23:39 devzerodevzero 2,6805 gold badges38 silver badges59 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

Well, your code does work as it is for me...

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

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

See in the REPL.

Maybe it's your browser, but I guess it might also be the REPL itself (if that's what you were using) that may have some issues with <svelte:window /> events, and displays outdated logs...

Actually, your solution would do the opposite of what you want, and cause the warning:

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

From 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.

With that out of the way, Svelte's way to add options to event listeners is with modifiers.

For example:

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

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

They're binable, but preventDefault and passive don't go well together, so let's use another one:

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

See Svelte's docs on events for available modifiers, and details:

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={...}.

Currently, there's no way to do this idiomatically with an event handler, because Chrome broke the web by making certain event listeners passive by default. There's an open Svelte issue that would address this.

In the meantime, the most idiomatic way would probably be to use an action:

<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.

本文标签: javascriptHow to add parameters to a window eventmouse wheel in svelteStack Overflow