概述
需要注意的点:
火狐的鼠标滚轮事件是DOMMouseScroll
事件参数兼容:e=window.event||e;(下面省略)
preventDefault()函数取消的是默认事件,不会把我们自己添加的事件处理删除
实验开始
在下面验证例子的基础上实验,实验之间代码没有干涉:
1.原样输出:
在元素内无论是手动拉动滚动条还是滚动鼠标滚轮,'d'都是无法出现的。而当元素滚动到达顶部或底部的时候,输出的是就有'd'了,但是这个时候并没有输出'b',说明scroll事件本来就没有发生冒泡。而document的scroll事件是由于其他因素触发的。
2.在element的mousewheel事件处理里把冒泡取消:
e.stopPropagation();
这时候在元素内滚动鼠标滚轮,'c'始终是无法出现的,说明我们阻止mousewheel事件的冒泡成功了。但是在滚动条到达底部或顶部时,虽然'c'依旧没有出现,但是'd'却出现了,说明这个时候的document的scroll事件是靠element的mousewheel来触发的。
到这里就出现一个问题:element的mousewheel事件在默认处理里对这一情形进行了处理吗?
3.在element的mousewheel事件处理里取消默认处理:
e.preventDefault();
这时候在元素内滚动鼠标,只会有'a'、'c'会出现,页面也不会滚动。说明鼠标滚轮滚动element页面的效果是由element的mousewheel默认事件处理来的。这个时候留意实验1中滚轮滚动一下'b'的输出数量,大概就能猜到默认处理的过程。
4.在element的mousewheel里添加一个自己的页面滚动(与默认处理的滚动方向相反):
element.scrollTop+=e.wheelDelta>0?30:-30;//手动添加的页面滚动
这个时候在元素内滚动鼠标,你会发现即使滚动到顶部或底部,元素外的页面并不会滚动,且并没有输出'd',也就是document的scroll事件没有触发。不好的一点是你在滚动到底部或顶部时,继续滚动鼠标的话,元素内还是会滚动,只不过是先下再上(或先上再下)地波动一下。
5.在element的mousewheel里添加一个自己的页面滚动(与默认处理的滚动方向相同):
element.scrollTop+=e.wheelDelta<0?30:-30;//手动添加的页面滚动
这个时候在元素内滚动鼠标,你会发现即使滚动到顶部或底部,元素外的页面跟着滚动,且输出'd',也就是document的scroll事件触发了。
这里需要注意到一点:元素的scrollTop属性是无法无限增加和减少的,到了滚动的顶部或底部后只能反向变化(可以自行输出测试)。
6.在实验5的基础上,将滚动的距离调整到很大:
element.scrollTop+=e.wheelDelta<0?300:-300;(值要大等于滚动行程)
认真观察输出的'b'的个数,和实验1的对比,你会发现这次只有1个'b',而且还输出了'd',而且'd'的数量还不少。经过一些其他的实验,得到:默认事件处理里的判断大概如下:
(function scroll(element){
for(var i=0;i<12;i++){
var temp=element.scrollTop;
element.scrollTop+=e.wheelDelta<0?10:-10; //滚动算法肯定不是这个,这里只是简单演示
if(temp!= element.scrollTop){
//滚动‘消息树’的下一个元素(和冒泡是一个列表)
var newEle=....//消息树怎么获取我不懂
scroll(newEle);
return;
}
}
})();
验证例子:
addEventListener(element,'mousewheel',function(e){
console.log('a');
});
addEventListener(element,'scroll',function(e){
console.log('b');
});
addEventListener(document.documentElement,'mousewheel',function(e){
console.log('c');
});
addEventListener(document,'scroll',function(e){
console.log('d');
});
结论:通过上面的6个实验,很容易发现在元素的mousewheel的默认处理事件里对scrollTop属性进行变化和判断,如果没有发生变化就对外部元素进行滚动一下(具体滚动算法不懂,滚动距离和鼠标滚一下是一样的),以此类推,如果下一个元素到边界了,就再下一个。而这个过程和冒泡是没有关系的,只是当前元素的mousewheel默认事件处理进行的。
应用:因此为了实现元素滚动到底时继续滚动却不会使外部元素滚动,我们可以直接取消它的默认处理,然后给一个自己的滚动函数就可以了。至于怎么滚就看自己给什么函数了,而冒泡取不取消也看自己,上面的默认处理在冒泡和捕获阶段是不进行的。
例子如下:
addEventListener(element,'mousewheel',function(e){
console.log('a');
e.preventDefault();
// e.stopPropagation();
ulObj.scrollTop+=e.wheelDelta<0?20:-20;
});
addEventListener(element,'scroll',function(e){
console.log('b');
});
addEventListener(document.documentElement,'mousewheel',function(e){
console.log('c');
});
addEventListener(document,'scroll',function(e){
console.log('d');
});
最后
以上就是虚拟树叶为你收集整理的关于scroll和mousewheel事件的问题的全部内容,希望文章能够帮你解决关于scroll和mousewheel事件的问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复