「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
前言
前段时间开发了一个H5的活动专题页面,在这个H5专题页中有一个需求是点击按钮弹框显示活动详情。这个需求看似平平无奇。当中却蕴含着一些我们值得学习的知识点。点击穿透与滑动穿透
什么是点击穿透、滑动穿透
在这之前,我们必须先了解下移动端300ms延迟触发。为了实现浏览器双击缩放效果,浏览器需要鉴别出用户是否点击了屏幕两次。
由于移动端设备没有鼠标。因此用户的点击事件在移动端会被拆分为如下过程touchstart
-> touchmove
-> touchend -> click
当用户点击屏幕时,浏览器会分别监听这几个事件。
当touched事件触发之后。浏览器会在此做一个300ms延迟触发。这个300ms的延迟被用来鉴别用户是否双击了屏幕。
也正是因为这个延迟,导致了移动端的点击穿透
下面用一个例子来展示点击穿透:
//test.vue
<div v-show="showOverlay" class="overlay" >
<div class="rule-box">
<div class="form-box">
<div class="form-box-title">{{ title }}</div>
<div class="rules-box" v-html="filterRulesText">
</div>
</div>
<div>
<img @click="showOverlay =false" class="close-btn" src="../images/close.png" alt="">
</div>
</div>
</div>
</template>
<script>
export default {
name:'test',
props: {
rulesText: {
type: String,
default: ''
},
data(){
return {
title:'查看活动详情'
showOverlay:false
}
},
computed: {
filterRulesText() {
const str = this.rulesText
const newStr = str.replace(/\r\n|\n|\r/g, '<br/>')
// console.log(newStr)
return newStr
},
methods:{
init(){
this.showOverlay = true
}
}
}
</script>
//app.vue中
<template>
<div>
<Button @click="$refs.openDialog.init()">点击查看活动详情</Button>
<Test ref="openDialog"></Test>
</div>
<script>
import Test from '@/components/Test'
export default {
name:'app',
components:{Test}
}
大致效果如上图:当我点击图中的close
图片时,移动端整个屏幕的遮罩以及详情都会被隐藏掉,该组件也隐藏在了dom中。
由于浏览器的300ms延迟导致本应该作用在test组件中的click事件被穿透到了父组件的app中。
这就是点击穿透~~~ 滑动传统与点击穿透是一样的原理。
点击穿透解决方法
- 阻止浏览器的默认事件
e.preventDefault()
在vue中使用@click.stop
即可组件默认事件。 但并不是所有的浏览器都支持 - 禁止浏览器进行缩放也可以解决300ms延迟的问题。
- 增加弹框过渡动画
- 使用fastclick
滑动穿透解决方法
H5项目内容较多时,我们会增加滚动条使得body当中的内容可以滑动。
当用户点击查看详情时:如果详情的内容较少。那么我们的弹框里面的内容则不需要滑动
当你滑动弹框以外的内容时你会发现body中的内容竟然滑动了。这也是300ms延迟造成的。此时的解决方案很简单
我们只需要在vue使用事件修饰符就可以。
在遮罩层的div
中添加@touchmove.prevent
<div v-show="showOverlay" class="overlay" @touchmove.prevent>
当详情页的内容较多时。由于文字太多 我们需要用到滚动条。此时我们会给弹框详情加上overflow:scroll
添加后。你会发现 弹框中的滚动条失效了。 并不会滚动。
之所以如此 是因为我们之前使用@touchmove.prevent
阻止掉了body中的滚动条事件,但是该事件也同样作用到了弹框中。因此该方法不可用。
那么怎么解决呢?给body添加滚动隐藏的样式。当vue中showOverlay的值发生改变时修改body的样式:
//代码忽略。。。。
watch:{
showOverlay(val){
this.styleChange(val)
}
},
methods:{
styleChange(val){
let body = document.body
//val 为true时 添加overflow为hidden
if(val){
body.style.overflow = 'hidden'
}else{
body.style.overflow ='scroll'
}
}
}
这样就能解决掉滑动穿透的问题。 当然,如上代码你也可以封装成一个自定义指令~~~~~~
最后
文章若有不足之处,还请大家批评指出。
感谢您观看此篇文章 希望能给个👍评论收藏三连!你的点赞就是我写作的动力。