页面滚动时隐藏el-select下拉框(vue+eleme
问题描述:elementUi的el-select
下拉选择框,打开之后,直到失去焦点才会自动关闭。
在有滚动条的弹窗中使用时就会出现打开下拉框,滚动弹窗,el-select下拉框会超出弹窗范围的问题.
解决方案1. 监听鼠标滚轮事件mousewheel
缺点:手动拖动滚动条时,不起效
// 滚轮事件的监听于移除并返回当前滚轮滚动方向,取消监听执行scrollFunc第二个参数
export function scrollEven(scrollFunc) {
let isRemove = false
// 火狐浏览器
if (document.addEventListener) {
document.addEventListener('DOMMouseScroll', scroll, false)
} // W3C
document.addEventListener('mousewheel', scroll, false) // IE/Opera/Chrome/Safari
function scroll(e) {
// direct 是 1 向上,是 -1 向下
var direct = 0
e = e || window.event
if (e.wheelDelta) {
//IE/Opera/Chrome
direct = e.wheelDelta > 0 ? 1 : -1
} else if (e.detail) {
//Firefox
direct = e.detail < 0 ? 1 : -1
}
if (isRemove) {
document.removeEventListener('DOMMouseScroll', scroll, false)
document.removeEventListener('mousewheel', scroll, false) // IE/Opera/Chrome/Safari
}
scrollFunc(direct, removeScroll, e)
}
function removeScroll() {
isRemove = true
}
}
<template>
<div>
<el-button type="primary" @click="dialogVisible = true">Click</el-button>
<el-dialog title="滚动表单" :visible.sync="dialogVisible" width="50%">
<div style="height: 400px; overflow: auto">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-select ref="mySelect" v-model="form.name" placeholder="">
<el-option
v-for="item in 10"
:key="item"
:label="item"
:value="item"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
</div>
<div slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import { scrollEven } from '@/utils/event.js'
export default {
data() {
return {
dialogVisible: false,
form: { name: '' }
}
},
mounted() {
// 监听滚动
scrollEven((direct, removeScroll, event) => {
this.removeHandleScroll = removeScroll
this.handleScroll(direct, event)
})
},
destroyed() {
// 监听滚动
this.removeHandleScroll()
},
methods: {
// 滚动时关闭下拉框
removeHandleScroll() {},
handleScroll(direct, event) {
if (!event.target.className.includes('el-select-dropdown__item')) {
this.$refs.mySelect.blur()
}
}
}
}
</script>
<style></style>
解决方案2. Vue监听Scroll事件
已使用该方案解决问题
<template>
<div>
<el-button type="primary" @click="dialogVisible = true">Click</el-button>
<el-dialog title="滚动表单" :visible.sync="dialogVisible" width="50%">
<div ref="scrollDiv" style="height: 400px; overflow: auto">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-select ref="mySelect" v-model="form.name" placeholder="">
<el-option
v-for="item in 10"
:key="item"
:label="item"
:value="item"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
</div>
<div slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
form: { name: '' }
}
},
watch: {
dialogVisible: {
handler(val) {
if (val) {
this.$nextTick(() => {
this.$refs.scrollDiv.addEventListener('scroll', this.ScrollChange, true);
});
} else {
this.$refs.scrollDiv.removeEventListener('scroll', this.ScrollChange, true);
}
}
}
},
mounted() {
},
methods: {
ScrollChange(event) {
console.log('event', event)
this.$refs.mySelect && this.$refs.mySelect.blur()
}
}
}
</script>
解决方案3: 给滚动条所在的盒子加上Vue自定义指令
给父盒子绑定一个自定义指令directives
, 根据类名获取到所有的下拉框, 监听内容区滚动时将打开的下拉框样式改成关闭
directives里包含三个钩子
- bind:只调用一次,指令第一次绑定到元素时调用,进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用
- update:所在组件的 VNode 更新时调用
3.1 步骤
- 首先el-select标签要加上
:popper-append-to-body='false'
下拉框默认是会插入body下面的,也就是不在咱们的弹窗中,如果不在弹窗中,根据类名获取父盒子下的元素,这一步就走不通了 - 其次一定要找对父盒子,因为自定义是监听父盒子的滚动才会去处理关闭事件
- 最后 把v-closeSelect加在对应父盒子标签上
<template>
<div>
<el-button type="primary" @click="dialogVisible = true">Click</el-button>
<el-dialog title="滚动表单" :visible.sync="dialogVisible" width="50%">
<div v-closeSelect ref="scrollDiv" style="height: 400px; overflow: auto">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-select ref="mySelect" v-model="form.name" :popper-append-to-body="false">
<el-option v-for="item in 10" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="label">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
</div>
<div slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
directives: {
closeSelect: {
bind(el, binding, vnode) {
//这里el是有滚动条的父盒子
//获取盒子下所有下拉框
let target = el.getElementsByClassName('el-select-dropdown');
//处理方法 让所有下拉框隐藏
el.handler = () => {
for (let item of target) {
console.log('item', item);
item.style.display = 'none';
}
};
//监听父子滚动
el.addEventListener('scroll', el.handler);
}
}
},
data() {
return {
dialogVisible: false,
form: { name: '' }
};
}
};
</script>