element 滚动滚动条时,类似select这种下拉框,不会自动关闭,他会跟着屏幕跑,这样的用户体验就很low,所以要做到,滚动屏幕的时候,下拉框要失去焦点,做到隐藏,
fackClickOutSide.js
let lock = true;
let el = null;
const MousedownEvent = new Event('mousedown', {bubbles:true});
const MouseupEvent = new Event('mouseup', {bubbles:true});
const fakeClickOutSide = () => {
document.dispatchEvent(MousedownEvent);
document.dispatchEvent(MouseupEvent);
lock = true; // console.log('dispatchEvent');
};
const mousedownHandle = e => {
let classList = e.target.classList;
if(classList.contains('el-select__caret') || classList.contains('el-input__inner')) {
lock = false;
return;
}
if(lock) return;
fakeClickOutSide();
};
const mousewheelHandle = e => {
if(lock || e.target.classList.contains('el-select-dropdown__item') || e.target.parentNode.classList.contains('el-select-dropdown__item')) return;
fakeClickOutSide();
};
const eventListener = (type) => {
el[type + 'EventListener']('mousedown', mousedownHandle);
window[type + 'EventListener']('mousewheel', mousewheelHandle);
window[type + 'EventListener']('DOMMouseScroll', mousewheelHandle); // fireFox 3.5+
}
export default {
mounted() {
el = this.$root.$el;
el.addFakeClickOutSideEventCount = el.addFakeClickOutSideEventCount || 0;
(! el.addFakeClickOutSideEventCount) && this.$nextTick(() => {
eventListener('add');
});
el.addFakeClickOutSideEventCount += 1;
},
destroyed() {
eventListener('remove');
el.addFakeClickOutSideEventCount -= 1;
}
}
import fackClickOutSide from './fackClickOutSide.js'
export default {
name: 'App',
mixins:[fackClickOutSide]
}
2020/6/6 优化代码
在页面当中有部分的下拉是select+tree,此时的tree放在select的option中,当鼠标在tree上滚动时会发现,fackClickOutSide.js监测到滚动认为不是select的滚动,就会执行让select进行失去焦点,达到隐藏的效果,但是此时实际上我们在tree上的滚动是不应该关闭select的,开始的想法是想办法将tree上去除掉监控事件,发现没有什么好的办法,再往后就想到我自己搞一个输入框模拟select,下拉显示树用element的popover来显示,此时特殊的下拉就不会被检测到关闭了,而在main块滚动时hi想让它关闭,就监测滚动事件,发生变化就让它关闭。
template
<el-popover
ref="treeProp"
placement="bottom"
@show="showHandle"
@hide="hideHandle"
trigger="click">
<el-scrollbar class="treeScroll">
<el-tree
:data="prevTagArr"
show-checkbox
ref="tagTree"
node-key="code"
check-strictly
@check="checktagTreeNode"
>
</el-tree>
</el-scrollbar>
<el-input slot="reference" class="selInput" readonly suffix-icon="el-icon-arrow-down" v-model="formLabelAlign.parentTag" placeholder="请选择上级标签" ref="sarchTree" clearable @change="sarchTagChange()"></el-input>
</el-popover>
data
treeScroTop:0,
statusHandle:2
mounted
this.loadScrWatch()
methods
loadScrWatch(){
document.getElementsByClassName('main-wrap')[0].addEventListener('scroll', this.handleScroll)
},
showHandle(){
this.statusHandle = 1;
},
hideHandle(){
this.statusHandle = 2;
},
handleScroll(){
if(document.getElementsByClassName('main-wrap')[0].scrollTop!==this.treeScroTop){
this.treeScroTop=document.getElementsByClassName('main-wrap')[0].scrollTop
if(this.statusHandle === 1){
this.$refs.treeProp.doClose()
}
}
},
2020/6/10
上次的input模拟select有点小bug,就是不能删除内容,考虑到input的disable和readonly属性与clearble作用相反,不能同时存在,没想到好的解决办法,先那样放着,还没等抽过空来看,就被测试提出bug了,解决办法就是采用下拉select,但是给select的option手动隐藏掉。其他的代码保持不变即可。
<el-popover
ref="treeProp"
placement="bottom"
@show="showHandle"
@hide="hideHandle"
trigger="click">
<el-scrollbar class="treeScroll">
<el-tree
style="margin:20px 15px"
:data="catalogOptions"
show-checkbox
ref="tagTree"
node-key="code"
check-strictly
@check="checktagTreeNode"
>
</el-tree>
</el-scrollbar>
<el-select slot="reference" class="selInput" clearable popper-class='input_select_model' v-model="formLabelAlign.tapContents" placeholder="请选择标签目录" ref="sarchTree" @change="sarchTagChange()"></el-select>
</el-popover>
css
.input_select_model{
display: none!important;
}