【发布时间】:2021-06-19 20:36:23
【问题描述】:
我正在创建一个Dropdown.vue 组件。它有一个名为 name 的道具,这样我就可以使用任何我想要的 div 通过点击事件来触发它。
比如我有一个元素<button @click="openDropdown('notifications-dropdown')">test</test>
然后我有组件:<dropdown name="notifications-dropdown"><div>content</div></dropdown>
点击事件是从全局 Vue 对象的方法中处理的:
methods: {
openDropdown( name) {
EventBus.$emit('dropdown-opened', name);
}
}
在实际的 Dropdown 组件上,我有 Mounted 方法:
EventBus.$on('dropdown-opened', (name) => {
if (this.name == name) {
this.active = true;
}
});
这一切都很好,但是,我需要处理单击关闭元素功能,以便在未单击下拉列表时,active 布尔值更改为 false。
在下拉菜单中,我有:
methods: {
closeDropdown(e) {
if ( !this.$el.contains(e.target) ) {
this.active = false;
}
}
}
在mounted 和beforeDestroy 中,我有:
document.removeEventListener('click', this.closeDropdown)
然后问题就变成了,在触发下拉菜单的初始按钮单击时也会触发事件单击关闭元素。所以下拉菜单打开并立即关闭
我怎样才能使它在触发下拉菜单的初始按钮点击时不会触发关闭e.target 点击closeDropdown()。
但是,如果您再次单击触发器,我希望下拉菜单会关闭。
以下是完整代码:
Dropdown.vue
<template>
<Transition name="fade-in-scale">
<div @click.stop ref="thedropdown" v-if="active" class="dropdown-menu absolute bg-white border-l border-b border-r border-gray-200 top-100 w-72 right-0 md:w-84">
<slot></slot>
</div>
</Transition>
</template>
<script>
// @ is an alias to /src
export default {
name: 'Dropdown',
data() {
return {
active: false
}
},
props: {
name: String
},
computed: {
},
mounted() {
document.addEventListener('click', this.closeDropdown);
EventBus.$on('dropdown-opened', (name) => {
if (this.name == name) {
this.active = !this.active;
}
});
},
beforeDestroy () {
document.removeEventListener('click', this.closeDropdown)
},
watch: {
},
methods: {
closeDropdown(e) {
if ( !this.$el.contains(e.target) ) {
this.active = false;
}
}
}
}
</script>
<style lang="scss" scoped>
.dropdown-menu {
top:calc(100% + 5px);
}
.fade-in-scale-enter-active,
.fade-in-scale-leave-active {
transition: all 0.12s;
transform:scale(1) ;
opacity:1;
}
.fade-in-scale-enter,
.fade-in-scale-leave-to {
transform: scale(0.90);
opacity: 0;
}
</style>
app.blade.php
<button @click="openDropdown('notifications-dropdown')" type="button" class="p-2 outline-none focus:outline-none"></button>
<dropdown name="notifications-dropdown"></dropdown>
app.js
require('./bootstrap');
/**
* UI
*/
import Btn from './components/ui/Button.vue';
import Dropdown from './components/ui/Dropdown.vue';
const app = new Vue({
el: '#app',
components: {
Btn,
Dropdown
},
methods: {
openDropdown( name) {
EventBus.$emit('dropdown-opened', name);
}
}
});
【问题讨论】:
标签: vue.js