Vue2.x如何解决Element组件el-tooltip滚动时错位不消失的问题
作者:BreenCL
一、问题
在给列表中的某些值外层嵌套了Element组件中的el-tooltip
后,在滑动鼠标滑轮时el-tooltip
的提示框不会消失(或不会立即消失,被滚动到顶上),影响了界面的显示;
产生这种情况的原因是因为el-tooltip
是监听鼠标是否移动,所以当鼠标不移动只进行滚动的时候提示并不会消失,由于组件内设置了z-index
的属性,滚到上面后依然悬浮在页面上层影响界面的显示,具体问题如图所示:
二、解决
解决思路为监听滚动条的滚动事件,在触发滚动事件时将当前显示的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树上面;
这里再次触发文字提示el-tooltip
,可以发现每次显示的el-tooltip
都会在DOM树的最后,也就是document.getElementsByClassName
选中的元素数组集合中的最后一项;
此时事件源和元素都是已知了,直接利用事件源给元素设置样式即可,methods
中添加一个关闭事件即可,最后将这个事件在Vue
的mounted
钩子函数中调用即可,这时在触发滚动事件的一瞬间,当前显示的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.projectBar
为undefined
的情况,这里通过上面这些设置是不能满足效果的,因为滚动条元素没有获取到,自然也就不能添加事件,
这里需要用到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。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。