页面滚动时,当el-select超出可视区域 隐藏下拉框
问题描述:当页面滚动使得el-select组件超出视口时,其下拉框仍然显示在页面上。
阅读完两篇参考文档,又去看看阮老师关于IntersectionObserver
API的讲解,最终得出的解决方案如下: 通过使用IntersectionObserver
API,我们可以监听el-select
组件的可视状态。一旦组件不可见(即超出视口),我们将手动触发组件的失焦事件,从而收起下拉框。 针对于 el-select
位于对话框(Dialog
)中的情况。根据对话框的具体使用情况,可以在mounted
生命周期钩子中设置监听器,或者去监听对话框的visible
属性,并在其变化时进行相关处理。
实现
以下为监听对话框显示值的实现。 首先,我们在模板中为每个el-select
添加一个data-index
属性,以便能够唯一标识并操作它们(调用blur
方法):
html
<div ref="wrapperRef" class="view-container">
<div v-for="item,index in 10" :key="item" class="select-container">
<el-select ref="selectRef" :data-index="index" popper-class="select-popper-class" v-model="select[item]" size="small">
<el-option v-for="item in 10" :key="item" :value="item">{{ item }}</el-option>
</el-select>
</div>
</div>
然后,在Vue组件的watch
属性中,我们监听visible
(假设这是控制Dialog
显示的属性):
js
watch: {
visible: {
handler(val) {
if (val) {
// 使用$nextTick确保DOM更新完成后执行代码
this.$nextTick(() => {
const selectRefs = this.$refs.selectRef
this.observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const { isIntersecting, target } = entry
// isIntersecting表示是否出现在了root区域内
if (!isIntersecting) {
// 隐藏popover
selectRefs[target.dataset.index] && selectRefs[target.dataset.index].blur()
}
})
},
{
root: this.$refs.wrapperRef.$el // root指定目标元素所在的容器节点(即根元素)注意,容器元素必须是目标元素的祖先节点。
}
)
/**
* observe的参数是一个 DOM 节点对象。
* 如果要观察多个节点,就要多次调用这个方法。
* 在这里使用数组循环方法是因为我循环生成了多个el-select。实际业务中可以具体问题具体考虑
**/
selectRefs.forEach(ele=>this.observer.observe(ele.$el)) //观察每一个选择器
})
} else {
this.observer.disconnect() // 关闭观察器
}
},
immediate: true
}
},
总结
- 在
visible
属性变为true
时,使用$nextTick
确保DOM更新完成后执行代码。接着,创建一个IntersectionObserver
实例来监听每个el-select
元素的可视状态。当任意一个el-select
超出视口时(即isIntersecting
为false
),我们通过blur()
方法关闭其下拉框。 - 如果
visible
变为false
,表示对话框关闭,我们则断开观察器以避免不必要的性能开销。
注意:在实际应用中,visible可能需要根据具体情况进行替换,以适应不同的显示/隐藏逻辑。
通过上述方法,我们可以有效地解决页面滚动时el-select
下拉框未能自动隐藏的问题,提升用户体验。
参考
juejin.cn/post/726605... hellogithub2014.github.io/2019/02/26/... www.ruanyifeng.com/blog/2016/1...