NumberInput 鼠标滚轮处理忽略捕获阶段的事件过滤
P粉318928159
P粉318928159 2024-04-05 12:21:04
0
1
1549

非常简短的版本:

我有点卡住了,不太明白为什么这段代码确实可以拦截和防止鼠标滚轮事件被数字编辑解释以更改数字。我想了解为什么拦截捕获和过滤事件不起作用:

HTML 代码:

<p id="p-number-1">
  <input id="number-1" type="number" min="0" max="100" value="50" class="number-input">
</p>
<p id="log">
</p>

JavaScript 代码:

function log(m) {
  const logp = document.getElementById("log")
  logp.innerHTML += "" + m + "<br>";
}

log("Logging started")

const pnum1 = document.getElementById("p-number-1")
const num1 = document.getElementById("number-1")

pnum1.addEventListener("wheel", function(e) { 
    log("captured outer");
    e.stopPropagation();
}, true);

num1.addEventListener("wheel", function(e) { 
    log("bubble inner");
}, false);

num1.addEventListener("wheel", function(e) { 
    log("capture inner");
}, true);

function log(m) {
  const logp = document.getElementById("log")
  logp.innerHTML += "" + m + "<br>";
}

log("Logging started")

const pnum1 = document.getElementById("p-number-1")
const num1 = document.getElementById("number-1")

pnum1.addEventListener("wheel", function(e) { 
    log("captured outer");
    e.stopPropagation();
}, true);

num1.addEventListener("wheel", function(e) { 
    log("bubble inner");
}, false);

num1.addEventListener("wheel", function(e) { 
    log("capture inner");
}, true);

说明:单击输入的数字将其聚焦,然后使用鼠标滚轮。鼠标滚轮被 JavaScript 代码拦截,但即使我在捕获阶段停止了周围

上的传播,但仍然会更改数字。

为了您的方便:https://jsfiddle.net/Ljku4gha/6/

我想要实现什么目标?

我想使用默认的数字输入字段(实际上还有滑块)编写一个可重用的组件。我不希望用户能够使用这些输入上的滚轮来更改数字。相反,鼠标滚轮应该触发周围某些(未知!)div(最有可能)的事件,以实现滚动目的。所以我想阻止数字编辑(和滑块)以某种方式处理鼠标滚轮事件。

较长版本:我的分析/假设

我无法完全解释它,但对正在发生的事情有两个假设。

我的第一个想法,也是我认为最有可能的想法是,这是浏览器如何处理用户事件的产物(我认为关键字“用户代理”)。然而,如果有人能指出在哪里可以阅读浏览器如何处理用户事件,那将非常受欢迎。在那之前,我对浏览器中事件处理的理解如下:

  • 用户滚动鼠标滚轮
  • 轮到 JavaScript 处理事件
    • JavaScript 执行捕获/冒泡操作
    • 事件处理程序可以将事件标记为已处理 (preventDefault())
  • JavaScript 之外:如果 JavaScript 中的事件处理程序未调用 PreventDefault(),则“用户代理”将轮到处理该事件。由于对此没有细粒度的控制,因此这一步只能完全停止或继续。由于数字编辑的“默认处理”正在更改数字值,因此数字会更改并且不会发出滚动事件。

结果:*sad me*

但是,我认为这个理论最有道理,但也许它是完全错误的?!

另类无聊的解释:我监听了错误的事件?

也许我遗漏了一些东西,并且轮子事件被转换为我可以阻止Default()的其他事件?我找不到任何相关信息,但这对我来说非常有意义......也许?这甚至不是一个“卷轴”,我只能说这么多。


我主要想得到一些指导,帮助我理解为什么我所做的事情不起作用......并且也欢迎解决方案!

P粉318928159
P粉318928159

全部回复(1)
P粉262073176

使用 event.preventDefault() 阻止数字输入的默认行为。

我们有 2 项改进:

  • 仅在输入聚焦时(当滚轮更改值时)防止滚轮。这样,当输入未聚焦时,滚轮会像平常一样运行
  • 当输入聚焦时,会阻止默认情况并模糊输入,以便下一个滚轮事件滚动将再次起作用(您应该决定是否需要此调整)。

您无法通过捕获来解决这个问题,因为

不幸的是,当您捕获默认行为发生在事件冒泡到输入之前时

因此 stopPropagation() 在捕获阶段没有帮助。

const p = document.getElementById("p-number-1")
const num1 = document.getElementById("number-1")



num1.addEventListener("wheel", function(e) { 
    console.log("input wheel");
    if(e.target.matches(':focus')){
      console.log("input wheel prevented");
      e.preventDefault();
      e.target.blur();
    }
}, false);
p{
  height:1000px;
}
input{
  pointer-events: none1;
}

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板