【问题标题】:How to add parameters to a window event / mouse wheel in svelte如何在 svelte 中向窗口事件/鼠标滚轮添加参数
【发布时间】:2020-02-02 23:39:05
【问题描述】:

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

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

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

使用 svelte 这是我想出的:

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

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

无法在被动事件侦听器调用中阻止默认值。

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

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

但是我在提到如何做到这一点的苗条文档中找不到任何方法。那么你将如何以苗条的方式做到这一点?

【问题讨论】:

    标签: javascript svelte svelte-3


    【解决方案1】:

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

    <script>
      const handleWheel = e => {
        console.log(e);
        e.preventDefault();
      };
    </script>
    
    <svelte:window on:wheel={handleWheel} />
    

    in the REPL

    也许是你的浏览器,但我想它也可能是 REPL 本身(如果你使用的是这个),它可能对&lt;svelte:window /&gt; 事件有一些问题,并显示过时的日志......

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

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

    来自MDN

    被动

    一个布尔值,如果为真,则表明侦听器指定的函数永远不会调用 preventDefault()。如果被动侦听器确实调用了 preventDefault(),则用户代理只会生成控制台警告。

    除此之外,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 了解可用的修饰符和详细信息:

    以下修饰符可用:

    preventDefault — 在运行处理程序之前调用 event.preventDefault()

    stopPropagation — 调用 event.stopPropagation(),防止事件到达下一个元素

    被动 - 提高触摸/滚轮事件的滚动性能(Svelte 会在安全的地方自动添加它)

    capture — 在捕获阶段而不是冒泡阶段触发处理程序

    once — 在第一次运行后删除处理程序

    修饰符可以链接在一起,例如on:click|once|capture={...}.

    【讨论】:

    • 似乎 |passive 修饰符将被动设置为真,而不是假。但我可以通过 onMount 函数解决这个问题,参见此处的示例(适用于 chrome)svelte.dev/repl/8a3717b985474d1cbd2bd6ce28a80c15?version=3.18.1
    • 顺便说一句,你是对的,我的代码示例在应该为假的地方是真的。我已经在问题中解决了这个问题
    • 您的解决方案完全有效。 Svelte 并没有将你与普通 JS 完全隔离开来,恰恰相反。如果您认为这对您最有效,您应该将其发布为答案并接受它。话虽如此,&lt;svelte:window on:wheel|preventDefault={handleWheel} /&gt; 在 Chrome / 桌面上对我来说正在按预期工作(防止滚动)......它不适合你吗?你的浏览器是什么?
    • |PreventDefault 阻止我滚动,但我只想在鼠标悬停在给定元素(日历)上时阻止滚动
    • 有点意思。您可以将其添加到页面上的任何元素:&lt;div on:wheel|preventDefault={handleWheel}&gt;REPL。 REPL 中的结果并不完美。浏览器对滚动事件很敏感,因为它会破坏性能。我会尝试在mouseenter / mouseleave 中切换一个标志,并在标志打开时防止在窗口上的wheel 中滚动。
    【解决方案2】:

    目前,没有办法使用事件处理程序惯用地执行此操作,因为 Chrome broke the web 默认情况下使某些事件侦听器处于被动状态。有一个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.

    【讨论】:

    猜你喜欢
    • 2010-09-25
    • 2014-08-14
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多