最近开发过程当中遇到一些小问题(彷佛问题老是那么多),但一直没什么时间去优化与解决。程序员不能被业务绑架,有时间仍是花点在代码上😀,开始此次的vue尝试吧。css
【遇到的问题】html
在一个可滑动列表页弹出一个全屏蒙层,蒙层固定,中间一块显示消息框,当用手滑动蒙层空白处时,滑动事件会穿透到底部列表页,致使列表页的滑动。vue
【要实现的目标】程序员
1. 滑动蒙层空白处不让滑动事件穿透。 浏览器
2. 当蒙层消息框文字多时,要让文字可上下滑动。post
要实现的效果其实以下:优化
【实现思路】this
1. vue提供的 @touchmove.prevent 能够用来阻止滑动,可是这个方法会对其内的子div的滑动事件也禁止掉了,这样会致使中间文字没法滑动。若是没有中间滑动需求,用 @touchmove.prevent 实现是一个很好的方法。url
2. 蒙层设为fixed悬浮在最上,底部列表设置overflow-y: hidden;这样能够列表内容就不能够滑了,但实际过程当中没有效果,因而想到继续往列表父div向上追溯,对body和html标签设置相关样式,这样就控制住了底部列表滑动问题。spa
3. 蒙层空白处点击事件与中间文字点击事件处理,防止事件冒泡带来其余bug。
【相关实现代码】
1. html代码都是比较简单,列表页for循环实现;蒙层用一个变量控制其显示和隐藏。但这里有几个注意点: a. 给上面列表的div动态绑定了 noScroll class,它的做用是当消息蒙层显示时切换到相关的css样式; b. 弹出的全屏蒙层,加有点击事件是为了点空白处让蒙层消失,但这里对显示的每行文字还加了@click.stop="messageTitleClick(num)"这个方法,为何加它呢——是由于蒙层空白处的点击方法对整个蒙层都生效,在文字上加上这个方法能够屏蔽掉蒙层点击方法的影响,即便这个方法里什么也不作它也是有做用的,另外这个方法上加了stop是为了防止它的点击事件穿透到后面的div。代码以下:
<!-- 列表 -->
<div :class="{noScroll: isShowPopup}">
<div class="item" v-for="num in 50" @click="itemClick(num)"> <div style="width:100%">点击item{{num}}</div> </div> </div> <!-- 蒙层 --> <div v-if="isShowPopup" class="popup" @click="popUpEmptyClick()"> <div class="message"> <p class="message-title" v-for="num in 30" @click.stop="messageTitleClick(num)"> 消息提示 {{num}} </p> </div> </div>
2. 给整个列表动态绑定的css以下
/* 当前蒙层显示时生效 */ .noScroll { overflow-y: hidden; }
3. 给列表整个div动态绑定 .noScroll 后,底部列表照样能够滑动,因此考虑继续向上追溯。利用watch监听蒙层是否显示,当显示时,设置body相应样式;但蒙层消失时,body样式恢复。可是在vue里怎么操做body里,虽然vue是数据驱动的,不提倡直接操做Dom。但此刻我也是没什么好办法了,就直接操做Dom了。以下:
watch: { isShowPopup(newVal, oldVal) { if (newVal == true) { let cssStr = "overflow-y: hidden; height: 100%;"; document.getElementsByTagName('html')[0].style.cssText = cssStr; document.body.style.cssText = cssStr; } else { let cssStr = "overflow-y: auto; height: auto;"; document.getElementsByTagName('html')[0].style.cssText = cssStr; document.body.style.cssText = cssStr; } // 下面须要这两行代码,兼容不一样浏览器 document.body.scrollTop = this.pageScrollYoffset; window.scroll(0, this.pageScrollYoffset); } }