记Event对象的bubbles属性

最近在一个移动端项目中开发组件时用到了scroll事件,但是给window绑上事件一直不触发。调试半天也没发现问题,后来百度到一篇文章解决了问题。
我们在一个子组件中监听window的scroll:

    window.addEventListener('scroll', function (e) {
        console.log(e);
    });

文章提到给addEventListener加上第三个参数true

    window.addEventListener('scroll', function (e) {
        console.log(e);
    }, true);

试了下问题解决。

文章解释说:

  1. 子组件mounted里addEventListener的时候,第三参数要设置为true,因为子组件滚动是捕获事件,父组件滚动是冒泡事件,addEventListener第三参数默认false只监听冒泡事件,所以子组件的捕获事件默认监听不到,改为true才可以.

  2. 这时候子组件和父组件的滚动都能触发事件,区别前者是捕获后者是冒泡,通过查阅event的文档得知,冒泡事件event.bubbles值是true,捕获事件的值是false.所以通过addEventListener的回调函数判断event的bubbles值即可区分是父组件滚动还是子组件滚动.
    乍一看解释好像能说得通。

经过大胆质疑,小心求证发现不是这样。
主要问题出在第二条解释,其实不管什么框架最终都会实现成html,那么在页面中就不存在父组件和子组件这一说法,同一种事件表现肯定是一致的。最重要的是一个关键词:

event.bubbles

bubbles官方解释是:

是否为起泡事件

其实就是指该事件是否会向上冒泡。scroll事件的bubbles是false,也就是说该事件在目标元素触发后就不会再向上冒泡了。而我们第一次的方式,是在冒泡阶段捕获。所以自然不会触发!

等一下,有点问题,我在window上监听,window就是我的目标元素啊。找了一下样式,发现我的html,body元素高度成了100%,所以其实发生scroll是body下的子元素,而scroll不会冒泡所以才出现这个问题。

那问题又来了,第二种方式是否可以?

其实第二种方式并不合适,主要问题在于: 我们在给window监听了一个scroll事件,并且是在捕获阶段,那页面任何元素的scroll事件都会在被调用,这样会出现干扰,需要在该事件排除其他元素引起的scroll。但是这样有点麻烦,换个思路,不监听window的scroll,直接在发生滚动的元素上监听就ok了。

另外再着重的说下那个解释,

通过addEventListener的回调函数判断event的bubbles值即可区分是父组件滚动还是子组件滚动.

scroll事件根据W3C标准,在document被触发时bubbles是true,而在其他元素下被触发时为false。在事件回调函数里,无法通过event的bubbles值来判断父组件滚动还是子组件滚动。

另外: 事件好像不分捕获事件和冒泡事件,而是事件会有捕获和冒泡这两个阶段。

最后要感谢这个文章的作者,要不然连解决问题的路子都找不到。

发表评论

电子邮件地址不会被公开。 必填项已用*标注