Vue2.x解决Element组件el-tooltip滚动时错位不消失的问题

Vue2.x解决Element组件el-tooltip滚动时错位不消失的问题

一、问题

  • 在给列表中的某些值外层嵌套了Element组件中的el-tooltip后,在滑动鼠标滑轮时el-tooltip的提示框不会消失(或不会立即消失,被滚动到顶上),影响了界面的显示;

  • 产生这种情况的原因是因为el-tooltip是监听鼠标是否移动,所以当鼠标不移动只进行滚动的时候提示并不会消失,由于组件内设置了z-index的属性,滚到上面后依然悬浮在页面上层影响界面的显示,具体问题如图所示:
    Vue2.x解决Element组件el-tooltip滚动时错位不消失的问题_第1张图片

二、解决

  • 解决思路为监听滚动条的滚动事件,在触发滚动事件时将当前显示的el-tooltip设置display:none进行隐藏(Element也是通过这种方式隐藏该元素的,只是Element通过监听鼠标移动进行触发的);

  • 首先找到需要绑定事件的滚动条,我这里用的是Element的组件el-scrollbar,给它设置一个ref属性,后面通过该属性找到该滚动条在其滚动事件中进行操作。如果没有使用该组件可以去监听滚动事件,或者监听所需要的事件即可;

    <el-scrollbar
      class="scrollbar-for"
      ref="projectBar"
    >
        
        ...
    el-scrollbar>
    
  • 之后找到需要消失el-tooltip,因为列表的每一项都加了el-tooltip所以设置id并通过id找到需要消失的el-tooltip元素有点不太现实,如果通过class找到一个el-tooltip的元素集合数组,再去遍历数组给每一项设置display:none的属性开销会很大,这时候去观察整个界面的DOM结构,通过观察发现初始化界面后el-tooltip的元素并不会出现,悬停在要显示进行文字提示的地方触发tooltip才会使tooltip元素挂载到DOM树上面;
    Vue2.x解决Element组件el-tooltip滚动时错位不消失的问题_第2张图片
    Vue2.x解决Element组件el-tooltip滚动时错位不消失的问题_第3张图片

  • 这里再次触发文字提示el-tooltip,可以发现每次显示的el-tooltip都会在DOM树的最后,也就是document.getElementsByClassName选中的元素数组集合中的最后一项
    Vue2.x解决Element组件el-tooltip滚动时错位不消失的问题_第4张图片

  • 此时事件源和元素都是已知了,直接利用事件源给元素设置样式即可,methods中添加一个关闭事件即可,最后将这个事件在Vuemounted钩子函数中调用即可,这时在触发滚动事件的一瞬间,当前显示的el-tooltip会直接被隐藏掉,代码如下:

    closeTooltip() {
    	// 此处事件源可以替换,按需切换即可
        this.$refs.projectBar.wrap.onscroll = () => {
            let list = document.getElementsByClassName('el-tooltip__popper')
            if (list.length > 0) {
                list[list.length - 1].style.display = 'none'
            }
        }
    }
    
  • 一般到这里就解决了,但是注意一下如果你也使用的是弹窗其它弹出样式的组件,会出现this.$refs.projectBarundefined的情况,这里通过上面这些设置是不能满足效果的,因为滚动条元素没有获取到,自然也就不能添加事件,这里需要用到Vue的另一个事件this.$nextTick(),我这里使用了弹窗el-dialog,弹窗中的数据也是通过点击某个DOM元素(这里可能是按钮或者其它标签DOM元素)后进行获取的,所以需要在获取数据的事件中调用this.$nextTick()等待DOM更新后再调用上述的closeTooltip()方法,这时this.$refs.projectBar就不会再为undefined了,自然也就能通过绑定事件去使el-tooltip消失了,代码如下:

    // 获取弹窗中的工程数据,该方法在点击页面中的按钮后进行调用
    async showProject(item, type) {
        // 调用接口获取数据
        ...
        // 更新列表数据
        ...
        this.projectList = res.data
        ...
        // 打开弹窗dialog
        ...
        // 滚动时设置el-tooltip消失
        this.$nextTick(() => {
            this.closeTooltip()
        })
    }
    // 设置el-tooltip消失
    closeTooltip() {
    	// 此处事件源可以替换,按需切换即可
        this.$refs.projectBar.wrap.onscroll = () => {
            let list = document.getElementsByClassName('el-tooltip__popper')
            if (list.length > 0) {
                list[list.length - 1].style.display = 'none'
            }
        }
    }
    
  • 顺带一提Vue.nextTick([callback,context]),官方定义为:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新之后的DOM

到这里问题就解决了,有更好的解决方式欢迎讨论补充!

你可能感兴趣的:(Vue,vue,elementui,vue.js)