阻止document滚动的默认行为,为什么其子元素也不能滚动了?

<ul class="box">
    <li>item1</li>
    <li>item2</li>
    <li>item3</li>
    <li>item4</li>
    <li>item5</li>
    <li>item6</li>
    <li>item7</li>
    <li>item8</li>
    <li>item9</li>
    <li>item10</li>
    <li>item11</li>
    <li>item12</li>
    <li>item13</li>
    <li>item14</li>
    <li>item15</li>
    <li>item16</li>
    <li>item17</li>
    <li>item18</li>
    <li>item19</li>
    <li>item20</li>
</ul>
<script>
    document.addEventListener('mousewheel', function(e){
        e.preventDefault();
    }, false);
    document.querySelector('.box').addEventListener('mousewheel', function(e) {
        // 如果不阻止冒泡,box就不能滚动
        e.stopPropagation();
    }, false);
</script>

如上,我在document上阻止了滚动默认引起页面滚动的行为,box元素如果不阻止冒泡,也不能滚动了,这是为什么?

阅读 5.7k
2 个回答

首先一点:
如果一个事件有默认的触发动作,那么要等到冒泡过程执行完毕,才会执行-没有被中途阻止的话

代码修改下,能看的更清楚

<script>
    document.addEventListener('mousewheel', function(e){
        console.log('document mousewheel');
        e.preventDefault();
    }, false);
    document.querySelector('.box').addEventListener('mousewheel', function(e) {
        console.log('.box mousewheel');
        // 如果不阻止冒泡,box就不能滚动
        e.stopPropagation();
    }, false);
</script>

1)mousewheel是支持事件冒泡的
2)mousewheel正常的事件冒泡顺序为li->ul->document
3)你在ul.box中添加了事件监听并执行了e.stopPropagation();那么冒泡顺序变为li->ul,不会到达document,也就意味者document上绑定的mousewheel事件将不会被触发-能看到.box mouse wheel输出而看不到document mousewheel输出e.preventDefault()无法执行到,默认的滚动行为没有被阻止,滚动自然就发生了
4)那么当e.stopPropagation()注释掉,事件冒泡走正常的流程,document中mousewheel的事件回调将被执行-e.preventDefault()被执行,默认滚动动作就被阻止,就不会发生了

额,感觉你脑洞有点大,头一次看到这么玩儿的。。

如果你想禁用页面滚动,为什么不直接给htmlbody加上overflow: hidden;呢?

上面说的是常规正常的做法,而且也没什么兼容性问题。
(不过好吧,当然,移动端是阻止不了的,因为移动端浏览器没有滚动条,但在PC浏览器端是绝对可行的)

那下面来说说你的做法。
mousewheel兼容性很差,比如不兼容Firefox,在Firefox上用的是DOMMouseScroll
而且通过mousewheel来禁用的话,还是可以用鼠标拖拽滚动条的。

以上。希望可以帮到你 :P

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题