javascript - Eveniment blur pentru componenta personalizată Vue
Ce am
Un DropDown personalizat cu un câmp de text pentru filtrare deasupra. DropDown-ul poate fi deschis independent de câmpul de text pentru filtrare.
Ceea ce vreau
Comportamentul dorit ar fi ca meniul derulant să se închidă atunci când câmpul de filtrare își pierde focusul și, de asemenea, când dau click cu mouse-ul în afara meniului derulant, astfel încât meniul derulant să își piardă focusul.
Ceea ce am încercat
- Leagă-te de evenimentul blur pe elementul meu div rădăcină în control, care nu se declanșează deloc.
- De asemenea, nu am putut găsi nimic despre metodele componentelor interne pe care aș putea să le suprascriu.
Cod
<div @blur="onRootLostFocus">
...
</div>
...
...
...
onRootLostFocus() {
console.log('LostFocus');
this.deactivateSearchPanel();
this.deactivateSelectionPanel();
}
Soluție
Am ratat faptul că un div are nevoie de tabindex="0" pentru a putea fi focalizat, acest lucru mi-a rezolvat problema
Răspuns #1
Ceva de genul acesta?
Răspuns: Trebuie să setezi tabindex="0" pentru a-l face focalizabil.
Aici un dropdown personalizat cum ai putea să-l faci:
Vue.component("dropdown", {
props: ["value"],
data(){
return {
open: false,
options: ["BMW", "Fiat", "Citroen", "Audi", "Tesla"]
}
},
methods: {
toggleDropdown() {
this.open = !this.open;
},
closeDropdown(){
this.open = false;
},
selectOption(option) {
this.$emit("input", option);
}
},
template: `<div class="dropdown">
<div @blur="closeDropdown" tabindex="0" ref="dropdown" @click="toggleDropdown" class="select">
{{ value }}
</div>
<div class="options" :style="{'max-height': open ? '300px' : '0px'}">
<div v-for="option in options" @mousedown="selectOption(option)" class="option">
{{ option }}
</div>
</div>
</div>`
})
new Vue({
el: "#app",
data: {
selectedCar: "BMW"
}
}).dropdown {
width: 200px;
position: relative;
}
.select {
height: 40px;
position: absolute;
left: 0;
width: 100%;
background: green;
display: flex;
justify-content: center;
align-items: center;
color: white;
cursor: pointer;
}
.option {
width: 100%;
height: 40px;
background: darkgreen;
color: white;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.option:hover {
background: green;
}
.options {
overflow: hidden;
transition: max-height 200ms;
}<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"> <p>
{{ selectedCar }}</p>
<dropdown v-model="selectedCar" />
</div>