在实际工程中有时会用到消息提示组件el-tooltip,会发现如果当前页面点开了消息提示之后并没有进行其它点击操作时,那个弹出的el-tooltip__popper是不会消失的,比如点击出现弹框后,我们只是进行了页面的上下滑动,那个弹窗会一直固定在那个位置,并不会跟随滑动而改变它在视口中的位置,当然这种情况是出现在移动端或者ipad上。
首先element ui这个组件库主要是用来应用在电脑操作的项目上,它们对于事件的监听也是对使用电脑过程中的事件进行监听,比如鼠标的各个事件,我们现在谈到的这个组件监听到的是鼠标的移入移出事件,而换到移动端上是没有鼠标的移入移出事件的,换成手势动作是手指点击,出现弹框,再点击任意地方收起弹窗,但是我们不能保证每次点出弹窗都会有点击其他地方的这个操作,而且这样也显得很不合理,所以在开发过程中我想到了一种思路,就是希望在页面发生滑动时也可以达到和点击其它地方一样的效果,点击其它地方达到的效果无非就是将el-tooltip__popper样式中的 display值变成none,因为在使用过程中我们可以观察到控制el-tooltip__popper显示与隐藏的就是它自带的display属性
第一步:准备一个用来保存页面滚动时距离的参数,之后要通过监听它的值是否发生改变来判断页面是否发生了滑动
data(){ return { scrolTop :0 } }
第二步:监听页面的滚动事件
之后对于弹窗样式修改的操作就是要在这个监听中进行的,对于window的监听在原则上在created和mounted中都可以的,但是这里的操作涉及到获取dom,会出问题,在这里方便一些,不需要操作中用this.$nextTick()进行修饰。 注意这里要加第三个参数为true,改为事件捕获状态,不然是监听不到嵌在window中这个事件的
mounted(){ window.addEventListenr( 'scroll' , function(){} , true ) }
第三步:书写函数的处理逻辑
上面这个函数中的就是对定义的变量scrollTop进行数据的获取,但是这个函数需要单独给外层盒子添加滚动事件,直接写在window函数中是不生效的,所以上面才通过捕获来捕获事件的发生
<template>
<div @scroll='scrollHandle'></div>
</template>
........
methods(){
scrollHandle(){
this.scrollTop = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset }
}
mounted(){ window.addEventListenr( 'scroll' , this. scrollHandle , true ) } // 这里函数不需要加括号调用,滚动时会自己调用
第四步:监听变量的值,如果值发生变化就说明页面发生了滚动,就将弹框的display赋值为none
watch(){
scrollTop:{handler(newVal,oldVal){ }
let toolTipClass = document.getElementByClassName('el-tooltip__popper') // 获取到页面所有的popperDom,是个数组
if ( newVal !== oldVal ){ if( toolTipClass .length !==0){ for(let i=0 ;i<toollTipClass.length;i++) { toolTipClass[i].style.display='none'} } }
} }
当然也有一种情况,那就是通过滚动事件获取到的元素卷起高度一直不变,比如说在el-carousel-item中,获取到的scrollTop一直是0,这样一来监听这个变量变得没有意义了,那我们就可以通过自己手动来给这个变量赋值,让它成为一个可以通过页面滚动来实时变化的数值:
scrollHandle(){ //针对于在html整个页面中部分元素滚动,监听不到数据变化的情况
this.scrollTop += 1
}
为了优化的话可以通过定时器每几秒将这个变量值为初始值
此时还是存在问题:即使在滑动后展示的提示信息消失了,也只是消失了而已,也就是说点击这个按钮,然后直接滑动页面,提示信息会消失,再次点击这个按钮提示信息并不会出现,需要点击页面的其它地方后,再点击这个按钮提示信息才会出现,因为这种办法没有在根本上解决这个问题,没有在滚动后失去焦点。
所以,我目前还不知道有什么特别好的办法解决这种问题,自己的话手写html+css也很容易实现和组件一样的效果