Vue
2.x解决Element组件el-tooltip
滚动时错位不消失的问题在给列表中的某些值外层嵌套了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。
到这里问题就解决了,有更好的解决方式欢迎讨论补充!