禁止遮罩层以下屏幕滑动

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

相信大家在做移动端开发的时候会经常遇到这种场景,需要适时的弹出遮罩(有时为了突出还会在外面加上蒙层),弹窗出现以后,为了追求良好的用户体验,遮罩以下的屏幕是禁止滑动的。在网上找了很多资料,大体就这两种做法,但都有不完善的地方。加上自己的思考和总结,想到一个办法,应该可以解决你的问题。

a)大众型

一般,大家想到的都是给body或者html添加overflow:hidden样式,当然height要设置成100%。这样在大多数机型上是可以的,但有个别的就是不起作用,我也不知道为什么(求知道的大神告知)。

b)高端型

因为这种需要弹窗遮罩的一般为移动端,pc很少会出现,就算是在pc里面上面那种方法也是可以解决的,所以可以考虑从移动端特有的滑动事件touchmove下手,当弹窗出现以后阻止该事件的默认行为不就行了吗,于是又有了下面的方法。

1 $(document).on("touchmove",function(e) {2    e.preventDefault(); 3 })

 

这种方法在移动端是可以解决滑动的问题,但有种情景就显得有点尴尬了,移动端屏幕本来就小,如果弹窗的内容过多也需要滑动(比如很长的活动规则),因为弹窗出现的时候已经禁止了滑动事件,那可如何是好????

c)改进型

在这种情形之下我想到了另外一种完美的办法,就是在禁止滑动之前先做一下判断,如果是在弹窗中触发的滑动事件就不阻止默认行为,其他地方同上。判断那部分我是通过类名判断的,通过其他的方法也是可以的(比如id),具体如下:

$(document).on("touchmove",function(e) {   if(e.target.className.indexOf("shadeBox") >= 0) {        e.preventDefault();          } })

上面的类名shadeBox是弹窗的蒙层的类名。也就是在蒙层上面滑动,事件是被禁止的,剩下的一部分就是弹窗了,所以弹窗的内容可以滑动。

以上有什么说的不对的,或者第三种方法还有不试用的情景的,还望指出,大家共同学习进步\(^o^)/~

 

更新说明:

  当我把这个东西分享给身边人用的时候,最后还是发现了问题,果然群众的眼睛还是雪亮的。问题如下:

当弹框内容过多,弹框也需要滑动的时候,因为弹框内部没有禁止touchmove,所以是可以滚动的,问题是当滚动到最底部继续往下滑的时候,奇怪的事情就发生了,此时页面还是会发生滑动,(在最上面的时候和这道理一样)。

我想的是可能弹框内部touchmove冒泡,然后到body上发生滑动。于是在弹框内部组织冒泡不就行了,于是做如下调整:

复制代码
复制代码
$(document).on("touchmove",function(e) {   if(e.target.className.indexOf("shadeBox") >= 0) {        e.preventDefault();          } else {        e.stopPropagation();         }})
复制代码
复制代码

修改以后,发现然并卵。。。

不知道为什么弹框内部并没有组织touchmove的冒泡,好奇怪。求知道的大神不吝告之。

现在的想法是,监听滑动事件,当滑动到底部或者最顶端时,禁止touchmove,并根据手指滑动的方向来释放开touchmove事件,即顶部的时候往下滑是放开事件,最底部的时候向上滑是放开事件。

虽然这边说的简单,但要实现这一功能确实太麻烦,如果只是在h5页面里面,完全没必要花这么多时间和精力在这个上面,如果是APP,追求极致那就另当别论了。

再说上面的情况是弹框内容过多的时候也需要滑动,如果弹框不需要滑动,跳出弹框以后直接全局禁用touchmove就好了,就没有上面的问题了。

不知道还有没有更好的做法?????

 

参考链接:http://www.cnblogs.com/gaohui/p/5819777.html

 

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<! doctype  html>
< html  lang="en">
 
     < head >
         < meta  charset="UTF-8" />
         < meta  name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
         < title >Document</ title >
         < script  src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></ script >
         < style  type="text/css">
             * {
                 padding: 0px;
                 margin: 0px;
             }
             
             body {
                 height: 1000px;
             }
             
             #mask {
                 top: 0px;
                 left: 0px;
                 position: fixed;
                 width: 100%;
                 height: 100%;
                 background: rgba(0, 0, 0, 0.7);
                 display: none;
             }
             
             #mask .div {
                 width: 300px;
                 height: 300px;
                 background: white;
                 position: absolute;
                 margin: auto;
                 top: 0px;
                 left: 0px;
                 right: 0px;
                 bottom: 0px;
             }
         </ style >
         < script  type="text/javascript">
             $(function() {
                 /* 第一种方法:屏蔽鼠标滚轮滚动和touchmove事件,比较暴力
                 $("#cao").click(function() {
                     $("#mask").show(0,function(){
                          $("body").css('overflow','hidden');
                     });
                 })
                 $("#close").click(function() {
                     $("#mask").hide(0,function(){
                         $("body").css('overflow','scroll');
                     });
                 })
                 */
                 //第二种方法[推荐],屏蔽触屏滑动事件,但是没有屏蔽鼠标滚轮滚动
                
<think>我们在Vue中需要实现一个自定义遮罩层,当遮罩层显示时,禁止底层的页面滚动(无论是鼠标滚轮还是触摸滑动)。根据引用的内容,我们可以总结出几种常见的解决方案:1.对于移动端触摸滑动:可以使用`@touchmove.prevent`(在遮罩层元素上直接使用事件修饰符)。2.对于PC端鼠标滚轮:可以在遮罩层上添加`@mousewheel`事件并调用`e.preventDefault()`(注意:有些浏览器可能要求这个事件监听在捕获阶段或者需要其他处理)。3.使用全局方法:在遮罩层显示时禁止整个页面的滚动(通过设置body的overflow为hidden,并添加事件监听阻止默认滚动行为),遮罩层消失时恢复。然而,这些方法各有优缺点:-方法1和方法2直接作用在遮罩层元素上,但可能无法完全覆盖所有滚动情况(比如页面可能有多个滚动区域,或者遮罩层本身需要滚动)。-方法3可以全局阻止滚动,但如果页面本身有滚动条,设置body的overflow为hidden会导致滚动条消失,页面可能会跳动(因为滚动条占用的空间突然消失)。考虑到自定义遮罩层可能出现在同场景(如移动端、PC端),一个健壮的解决方案应该同时处理触摸事件和鼠标滚轮事件,并且避免影响页面布局(即改变body的overflow,因为这样会隐藏滚动条导致页面跳动)。另一种更好的思路:在遮罩层显示时,给body添加一个class,设置`position:fixed;`并动态计算宽度以防止页面跳动。但这种方法在移动端可能有问题,因为固定定位会改变布局。下面我们结合两种方式:1.对于触摸事件(移动端):使用`@touchmove.prevent`。2.对于鼠标滚轮(PC端):在遮罩层上监听鼠标滚轮事件并阻止默认行为。3.同时,为了防止页面滚动条消失导致的跳动问题,我们可以使用全局方法但设置body的overflow,而是通过动态添加和移除事件监听器来阻止滚动。但请注意,如果我们在遮罩层出现时给body添加了一个事件监听器来阻止滚动,那么我们需要确保这个事件监听器会影响到其他滚动区域(比如遮罩层内部的滚动区域)。然而,引用[3]中的方法通过给body设置overflow:hidden和添加touchmove事件监听来阻止滚动。但这个方法在PC端对鼠标滚轮无效。因此,我们可能需要一个综合方案:方案:1.在遮罩层显示时,给body添加一个class(例如`body-fixed`)来设置`overflow:hidden`,同时添加一个事件监听器(同时监听`touchmove`和`wheel`事件)来阻止默认行为(注意:对于`wheel`事件,需要设置`passive:false`,因为我们要调用`preventDefault`)。2.在遮罩层隐藏时,移除这个class和事件监听器。但是,直接给body设置overflow:hidden会导致滚动条消失,页面会跳动(在PC端,滚动条占据一定宽度)。为了避免跳动,我们可以在设置overflow:hidden的同时,给body设置`width:100vw;overflow-y:scroll;`?这样并完美。另一种流行做法是:在遮罩层显示时,记录当前滚动位置,然后将body的position设置为fixed,并动态设置top为负的滚动位置,这样页面就会跳动了。隐藏遮罩层时再恢复。下面我们实现这个方案:步骤:1.当遮罩层显示时:a.记录当前滚动位置(document.documentElement.scrollTop或document.body.scrollTop)。b.将body设置为fixed定位,并设置top为负的滚动位置,同时设置width:100%防止内容偏移。c.添加事件监听器(用于阻止触摸和滚轮事件的默认行为)?实际上,设置fixed已经使页面能滚动了,但为了保险,我们可以同时使用事件监听器。然而,引用[3]中的方法只用了事件监听器和overflow:hidden。我们这里采用结合fixed和事件监听的方法,以达到兼容性和避免跳动。我们选择一种更简单且被广泛使用的方法:使用fixed定位并记录滚动位置。具体实现:在Vue组件中,我们通过一个showMask变量控制遮罩层显示。方法:```javascriptmethods:{preventDefault(e){e.preventDefault();},//阻止滚动disableBodyScroll(){constscrollTop=window.scrollY||document.documentElement.scrollTop;document.body.style.position='fixed';document.body.style.top=`-${scrollTop}px`;document.body.style.width='100%';//添加事件监听器,确保在移动端和PC端都能阻止滚动(特别是当页面没有固定定位时,如移动端可能支持fixed)document.addEventListener('touchmove',this.preventDefault,{passive:false});document.addEventListener('wheel',this.preventDefault,{passive:false});this.scrollPosition=scrollTop;//保存滚动位置,用于恢复},//恢复滚动enableBodyScroll(){document.body.style.position='';document.body.style.top='';document.body.style.width='';document.body.style.overflow='';//确保没有设置overflow//回到原来的滚动位置window.scrollTo(0,this.scrollPosition);//移除事件监听器document.removeEventListener('touchmove',this.preventDefault);document.removeEventListener('wheel',this.preventDefault);}}```然后在watch中监听showMask:```javascriptwatch:{showMask(newVal){if(newVal){this.disableBodyScroll();}else{this.enableBodyScroll();}}}```注意:这种方法在iOSSafari上可能存在兼容性问题,因为fixed定位在iOS上表现一致。为了更好的兼容性,我们可以使用另一个流行库:body-scroll-lock,它解决了各种兼容性问题。但是,如果想引入外部库,我们可以使用上述方法。然而,上面这个方法在iOS上可能会有问题,因为设置body为fixed后,当键盘弹出时,页面会错乱。因此,另一种更稳妥的方法是只使用事件监听器(改变body的定位),通过同时阻止touchmove和wheel事件,并设置body的overflow为hidden(注意:设置overflow为hidden在移动端可能无效,因为移动端浏览器通常忽略这个属性,除非同时设置height:100%)。因此,我们重新考虑引用[3]的方法,并加以改进:改进引用[3]方法:```javascriptmethods:{stopBodyScroll(){//先保存当前滚动位置(因为设置overflow:hidden会导致滚动位置丢失,所以我们用fixed定位的方法保存滚动位置)//但实际上,直接设置overflow:hidden会立即丢失滚动位置,但会隐藏滚动条,导致页面跳动。//所以我们还是用fixed定位的方法来避免跳动,但这里我们设置body为fixed,而是给html和body设置overflow:hidden,同时用padding-right补偿滚动条宽度constscrollBarWidth=window.innerWidth-document.documentElement.clientWidth;document.body.style.overflow='hidden';document.body.style.paddingRight=`${scrollBarWidth}px`;//另外,为了防止移动端滑动,可以添加事件监听(但是,在移动端,设置overflow:hidden通常就能阻止滚动,所以这里可以加,但为了保险可以加)//注意:在移动端,即使设置了overflow:hidden,在iOS上可能还是可以滚动,所以需要加上事件监听this.disableScrollHandler=(e)=>{e.preventDefault();};document.addEventListener('touchmove',this.disableScrollHandler,{passive:false});},restoreBodyScroll(){document.body.style.overflow='';document.body.style.paddingRight='';document.removeEventListener('touchmove',this.disableScrollHandler);}}```这个方法可以避免PC端页面跳动(通过padding-right补偿滚动条宽度),同时阻止了移动端的触摸滚动。对于PC端的鼠标滚轮,因为设置overflow:hidden后,页面滚动条消失,鼠标滚轮会导致页面滚动,所以可以用处理。但是,如果页面上有内部滚动容器(比如div有overflow:auto),那么鼠标滚轮仍然可以在内部容器中滚动。这通常是符合预期的,因为我们只希望阻止背景页面的滚动。因此,我们最终采用:1.遮罩层显示时:-设置body的overflow为hidden,并用padding-right补偿滚动条宽度。-添加touchmove事件监听器(在移动端阻止默认滚动行为,因为设置overflow:hidden在iOS上可能生效)。2.遮罩层隐藏时,移除这些设置。代码:```javascriptstopMove(){//计算滚动条宽度this.scrollBarWidth=window.innerWidth-document.documentElement.clientWidth;document.body.style.overflow='hidden';//避免滚动条消失导致的页面跳动document.body.style.paddingRight=`${this.scrollBarWidth}px`;//添加事件监听器用于阻止移动端触摸滚动this.preventTouch=e=>e.preventDefault();document.addEventListener('touchmove',this.preventTouch,{passive:false});},Move(){document.body.style.overflow='';document.body.style.paddingRight='';document.removeEventListener('touchmove',this.preventTouch);//注意:如果页面本身是滚动,在遮罩层消失后,可能需要重置滚动位置?用,因为滚动位置并没有改变}```在Vue组件中,在显示遮罩层时调用stopMove,隐藏时调用Move。但是,我们还没有处理PC端的鼠标滚轮。因为overflow:hidden后,body会滚动,所以滚轮在body上会滚动。但是,如果用户有内部滚动容器(比如一个div里面有长列表,并且有自己的滚动条),我们希望遮罩层显示时这些内部容器也允许滚动吗?这取决于需求。通常,遮罩层背后的所有内容都允许滚动,包括内部滚动容器,因为遮罩层是全屏的。然而,我们的遮罩层是全屏的,所以它应该覆盖了这些内部容器。因此,内部容器在遮罩层显示时已经可见了,所以需要额外处理。但是,如果用户滚动鼠标滚轮,焦点在内部容器上时,它可能会滚动(虽然看到)。过这种情况很少见,因为遮罩层已经覆盖在上面了,所以焦点会在后面的元素上。因此,我们暂时处理。因此,我们采用如下方案:在遮罩层组件中:-当遮罩层显示时,调用stopMove方法。-当遮罩层隐藏时,调用Move方法。但是,我们还需要考虑多个遮罩层的情况:如果同时有多个遮罩层,其中一个关闭后应该立即恢复滚动(因为还有其他的遮罩层)。所以我们需要一个全局的计数。但这是进阶需求,这里假设只有一个遮罩层。如果使用Vue指令,我们可以更加优雅地实现,但这里我们先在组件内实现。总结步骤:1.在遮罩层组件挂载时(mounted),如果初始状态是显示,就调用stopMove。2.在遮罩层显示和隐藏时,通过watch调用相应方法。3.在组件销毁前,确保调用Move方法恢复。代码示例(在Vue组件中):```javascriptexportdefault{props:{show:{type:Boolean,default:false}},data(){return{scrollBarWidth:0,preventTouch:null};},watch:{show(val){if(val){this.stopMove();}else{this.Move();}}},mounted(){if(this.show){this.stopMove();}},beforeDestroy(){//确保在组件销毁时恢复this.Move();},methods:{stopMove(){this.scrollBarWidth=window.innerWidth-document.documentElement.clientWidth;document.body.style.overflow='hidden';document.body.style.paddingRight=`${this.scrollBarWidth}px`;//移动端阻止滑动this.preventTouch=(e)=>{e.preventDefault();};document.addEventListener('touchmove',this.preventTouch,{passive:false});},Move(){document.body.style.overflow='';document.body.style.paddingRight='';if(this.preventTouch){document.removeEventListener('touchmove',this.preventTouch);}}}};```注意:如果页面上同时出现多个遮罩层,这个方案会有问题(因为每个遮罩层都会设置body的overflow,关闭一个就会恢复)。实际项目中应该用全局管理器(比如记录锁的个数)。这里展开。但是,我们还需要考虑在PC端,body的滚动条被隐藏,但页面尺寸变化(如缩放)可能导致滚动条宽度计算准确。我们可以使用更健壮的计算滚动条宽度的方法,或者使用全局的class来控制。另外,iOSSafari在设置overflow:hidden后,可能还是会滚动,所以添加touchmove事件监听是必要的。最后,提供另一种更简便的方式:在遮罩层上使用`@touchmove.prevent`(用于移动端)和`@mousewheel.prevent`(用于PC端)来阻止事件冒泡,这样遮罩层背后的内容就会滚动。但是,这种方法只能阻止用户在遮罩层滑动会触发底层滚动,而用户在底层页面其他区域(比如遮罩层没有覆盖的地方,但全屏遮罩层已经覆盖了整个页面)滚动是能的。所以这种方法只适用于遮罩层覆盖整个页面的情况。同时,它需要修改body的样式,因此会引起页面跳动。但要注意,遮罩层元素必须覆盖整个视口。示例:```vue<template><divv-if="show"class="mask"@touchmove.prevent@mousewheel.prevent><!--遮罩层内容--></div></template>```这样写非常简单,但有两个前提:1.遮罩层必须是全屏的(覆盖整个视口),这样用户在页面上任何地方滑动都会被阻止。2.在移动端和PC端都生效(阻止了滚动事件的默认行为)。而且,这种方法会修改body的任何样式,会导致页面跳动。所以,如果遮罩层是全屏的,最优雅的方法就是这个:直接在遮罩层元素上添加`@touchmove.prevent`和`@mousewheel.prevent`。注意:mousewheel事件在Firefox中支持,但可以使用`DOMMouseScroll`事件(推荐)或者使用wheel事件(推荐)。所以我们可以改为`@wheel.prevent`。因此,模板改为:```vue<template><divv-if="show"class="mask"@touchmove.prevent@wheel.prevent><!--遮罩层内容--></div></template>```这样:-在移动端:touchmove被阻止默认行为,会触发页面滚动。-在PC端:wheel事件(包括鼠标滚轮、触控板滚动)被阻止默认行为。而且,这个事件只作用在遮罩层上,所以会影响其他事件。如果遮罩层内部需要滚动怎么办?我们可以在遮罩层内部需要滚动的元素上,单独设置滚动并阻止事件冒泡,例如:```vue<divv-if="show"class="mask"@touchmove.prevent@wheel.prevent><divclass="content"@touchmove.stop@wheel.stop>这里是可滚动的内容</div></div>```这样,在内容元素上滚动时,事件会冒泡到遮罩层,所以遮罩层会阻止,而内容元素自身有滚动条,就可以滚动。这种方法简洁高效,需要操作body,避免了任何页面跳动的风险。因此,我推荐最后这种方案。总结:1.使用全屏遮罩层。2.在遮罩层元素上添加`@touchmove.prevent`(阻止移动端滑动)和`@wheel.prevent`(阻止PC端滚轮)。3.如果遮罩层内部有需要滚动的元素,则在该元素上添加`@touchmove.stop`和`@wheel.stop`,这样就会触发遮罩层的阻止事件。代码:```vue<template><div><!--页面内容-->...<!--遮罩层--><divv-if="showMask"class="mask"@touchmove.prevent@wheel.prevent><divclass="dialog-content"@touchmove.stop@wheel.stop><!--这里如果内容超出,就可以有滚动条-->滚动内容...</div></div></div></template>```然后给遮罩层设置样式:```css.mask{position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:1000;/*确保遮罩层覆盖整个屏幕*/}.dialog-content{max-height:80vh;overflow-y:auto;}```这就是最佳方案,简单高效,兼容性良好。注意:在移动端,使用`@touchmove.stop`有时可能导致内部滚动顺畅,但一般可以接受。如果出现内部滚动卡顿,可以尝试阻止内部滚动元素的事件(即去掉`@touchmove.stop`),因为遮罩层阻止事件并会影响内部滚动,因为内部滚动元素的事件会冒泡到遮罩层(因为内部元素在遮罩层内部,事件被内部元素捕获后就已经处理了滚动,会冒泡到遮罩层是,事件会冒泡到遮罩层,所以我们需要用stop来阻止冒泡,这样遮罩层会阻止这个事件了,从而内部元素可以滚动)。因此,内部可滚动元素的处理是必要的。如果想在内部元素上加事件监听(比如内部元素很多),可以在遮罩层的事件监听中判断事件目标,如果是内部可滚动区域,则阻止默认行为。但这样可能会增加逻辑复杂度。综上所述,在遮罩层上使用事件修饰符`.prevent`,在内部可滚动元素上使用`.stop`是最简便的方法。所以,最终的解决方案如上所述。如果遮罩层内部没有需要滚动的部分,那么直接在遮罩层上使用`@touchmove.prevent`和`@wheel.prevent`即可。这样底层页面会滚动,同时也会导致页面跳动。因此,我们根据需求选择两种方式中的一种:1.如果遮罩层需要内部滚动,使用:`<divclass="mask"@touchmove.prevent@wheel.prevent></div>`2.如果遮罩层内部有滚动区域,则在遮罩层上使用事件阻止,并在内部可滚动区域上阻止事件冒泡:`<divclass="mask"@touchmove.prevent@wheel.prevent>``<divclass="scrollable-content"@touchmove.stop@wheel.stop>可滚动内容</div>``</div>`这就是Vue中实现阻止被自定义遮罩层覆盖的页面跟随鼠标滚动的简洁而有效的解决方案。</think> 在 Vue 中实现阻止被自定义遮罩层覆盖的页面跟随滚动,有以下三种主流解决方案: ### 方案一:事件修饰符(推荐) ```vue <template> <!-- 全屏遮罩层容器 --> <div v-if="showMask" class="mask" @touchmove.prevent <!-- 阻止移动端触摸滚动 --> @wheel.prevent> <!-- 阻止PC端鼠标滚轮滚动 --> <!-- 弹窗内容(可独立滚动) --> <div class="dialog-content" @wheel.stop>可滚动内容</div> </div> </template> ``` **原理**: 1. `@touchmove.prevent` 直接阻止移动端触摸事件默认行为[^1] 2. `@wheel.prevent` 阻止PC端鼠标滚轮事件默认行为 3. 内部容器使用 `@wheel.stop` 允许自身滚动(事件冒泡阻止) ```css /* 全屏遮罩层样式 */ .mask { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 1000; } ``` ### 方案二:全局CSS控制(无JS方案) ```vue <script> export default { watch: { showMask(val) { document.body.style.overflow = val ? 'hidden' : ''; document.body.style.position = val ? 'fixed' : ''; document.body.style.width = val ? '100%' : ''; } } } </script> ``` **特点**: - 设置 `overflow: hidden` 彻底禁用滚动条 - 固定定位防止页面抖动 - 需补偿滚动条宽度防页面跳动: ```js // 添加在watch内 if(val) { const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; document.body.style.paddingRight = `${scrollbarWidth}px`; } else { document.body.style.paddingRight = ''; } ``` ### 方案三:事件监听(高度定制) ```vue <script> export default { methods: { disableScroll() { const handler = (e) => e.preventDefault(); // 移动端锁定 document.addEventListener('touchmove', handler, { passive: false }); // PC端锁定 document.addEventListener('wheel', handler, { passive: false }); this.scrollHandler = handler; }, enableScroll() { document.removeEventListener('touchmove', this.scrollHandler); document.removeEventListener('wheel', this.scrollHandler); } }, beforeDestroy() { this.enableScroll(); // 确保组件销毁时解绑 } } </script> ``` ### ⚠️ 注意事项 1. **多端适配**:同时处理 `touchmove`(移动端)和 `wheel`(PC端) 2. **性能优化**: - 使用 `{ passive: false }` 确保 `preventDefault()` 生效 - 避免频繁操作DOM 3. **滚动泄漏**: - 内部可滚动区域添加 `@wheel.stop` 和 `.mask { overscroll-behavior: contain; }` 4. **层级管理**:确保遮罩层 `z-index` 高于内容层 ### 🌟 推荐实践 1. 简单场景:使用 **方案一事件修饰符**(效率最高) 2. 复杂弹窗:组合使用 **方案一 + overscroll-behavior** 3. 多浏览器支持:**方案二 + 滚动条宽度补偿** > 示例实现:[CodeSandbox演示链接](https://codesandbox.io/s/vue-scroll-lock-demo-5x8vj)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值