vue中引入mousewheel事件及其兼容性处理

项目实现过程中需要对一个已经有纵向滚动条的table表格增加鼠标滚轮(mousewheel)事件,方便查看数据;其实现原理与我上一篇博客中的拖动事件类似,利用模拟出来的同一个滚动条来实现,滚动条设置的要点在于:1、滚动条与滚动槽的高度比例 应该等于 内容区(动态变化)和可视区的高度比例;滚动槽与可视区平齐,高度一样,;滚动条的高度则根据内容的高度等比例计算;2、各元素的定位采用绝对定位,其父元素采用相对定位,这样就能很好地设置样式;
布局与样式做好后,只需要在组件methods注册方法,在元素就位后调用该方法,在方法内部为表格绑定(mousewheel)事件;在这里需要考虑兼容性问题,firefox并不支持mousewheel事件,它对应的鼠标滚动事件为DOMMouseScroll事件,并且该事件仅能通过DOM2级(addEventListener)添加处理程序;并且判断鼠标滚动方向的方式也不一样,firefoxt通过detail属性判断,向前滚动该属性为-3,向后+3;其余浏览器通过wheelDelta属性,向前时为+120的倍数,向后为-120的倍数;具体内容可参考《js高级程序设计》事件一章;添加函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
scroll(){
this.wrapDiv = document.getElementById("wrap");
this.contentDiv = document.getElementById("context-table");
this.contentDiv1 = document.getElementById("context-table1");
this.sliderWrap = document.getElementById("sliderWrap");
this.slider = document.getElementById("slider");
//设置比例
let scale = this.wrapDiv.clientHeight / this.contentDiv.clientHeight;
if (scale < 1) {
this.mouseFlag = true;
let h1 = this.sliderWrap.clientHeight * scale;
h1 = (h1 < 50) ? 50 : h1;
this.slider.style.height = h1 + "px";/*滚动条高度动态变化*/
let y = 0;
let that = this;
//为firefox添加滚轮事件
if (document.addEventListener){
document.addEventListener('DOMMouseScroll',function (e) {
if(that.mouseFlag){
//console.log('scroll');
let event1 = window.event|| e;
y = (event1.detail > 0) ? y + 8 : y - 8;
y = (y < 0) ? 0 : y;
let max = that.sliderWrap.clientHeight - that.slider.clientHeight;
y = (y > max + 1) ? max + 1 : y;
that.slider.style.top = y + "px";
scale = that.wrapDiv.clientHeight / that.contentDiv.clientHeight;
let y1 = -y / scale;
that.contentDiv.style.top = y1 + "px";
that.contentDiv1.style.top = y1 + "px";
}
},false)
}
this.wrapDiv.onmousewheel = function (e) {
if (scale < 1) {
let event1 = window.event || e;
y = (event1.wheelDelta < 0) ? y + 8 : y - 8;
y = (y < 0) ? 0 : y;/*限定滚动范围*/
let max = that.sliderWrap.clientHeight - that.slider.clientHeight;
//console.log(scale, y, sliderWrap.clientHeight, slider.clientHeight);
y = (y > max + 1) ? max + 1 : y;
that.slider.style.top = y + "px";
scale = that.wrapDiv.clientHeight / that.contentDiv.clientHeight;
let y1 = -y / scale;
that.contentDiv.style.top = y1 + "px";
that.contentDiv1.style.top = y1 + "px";
}
}
}
else{/*当内容区高度小于等于可视区时,去除绑定的事件和滚动条*/
this.wrapDiv.onmousewheel =null;
if(document.addEventListener){
this.mouseFlag = false;
}
this.sliderWrap.style.visibility = 'hidden';
let height = this.contentDiv.clientHeight;
tableRight.style.height = height+72+'px';
this.wrapDiv.style.height = height+2+'px';
}
},

该函数在给firefox绑定的事件解绑时遇到了问题,由于removeEventListener()需要通过句柄来解绑,而addEventListener()通过句柄添加处理函数会导致event参数无法传递的问题;即使在需要解绑时给document绑定空的处理函数也无法覆盖前一个绑定函数;最后只好添加一个标志,在需要解绑函数时改变标志的值;在绑定函数中通过判断该标志的值来确定是否要做操作;

通过上述方式即可很好地实现鼠标滚动事件的效果,并不会有兼容性的问题出现。

注:若仅仅是为表格绑定单一的滚动事件,则可以不显示滚动条,甚至不设置滚动条;滚动条的作用仅仅是用来指示内容区滚动的位置,以及配合拖动事件使用;