我有一个HeaderSubmenu组件,如果点击一个按钮,它可以显示/隐藏一个下拉菜单。好的,但现在我尝试找到一个很好的解决方案,如果用户点击应用中的任何地方但不在此下拉菜单中,则会隐藏。
我将Vue 2.3.3与Vuex和VueRouter结合使用。
我的应用入门点:
'use strict';
import Vue from 'vue';
import VueRouter from 'vue-router';
import Vuex from 'vuex';
Vue.use(VueRouter);
Vue.use(Vuex);
import store_data from 'store';
import {router} from 'routes';
import App from 'app.vue';
var store = new Vuex.Store(store_data);
new Vue({
el: '#app',
store,
router: router,
render: function (createElement) {
return createElement(App)
}
})
HeaderSubmenu
组件的模板:
<template>
<li class="header-submenu">
<!-- button to show/hide the drop-down menu -->
<header-link v-bind="$props" :href="to ? false : '#'" @click.native="toggleMenu()">
<slot name="item"></slot>
</header-link>
<!-- drop-down menu -->
<ul class="submenu-list" :class="{'open': open, 'animated': animated}" @animationend="displaynone()">
<slot></slot>
</ul>
</li>
</template>
此组件位于我的应用中的某个位置,当用户点击toggleMenu()
上的其他位置时,我想调用他的<ul class="submenu-list">
方法。
我想到了一个全球事件总线,我的下拉菜单应该是&#34;注册&#34;并检测我的应用程序上的全局@click事件。如果注册的菜单不是点击的元素,我们会调用他的toggleMenu()
方法。
(理想情况下,我可以注册具有相同行为的其他元素。)
...但我根本不掌握vue事件系统。 如何检查某个元素上是否没有事件? 我不知道如何实现这一目标。你能帮助我吗 ?谢谢!
======编辑======
在Bert Evans的帮助下,我使用了这个自定义指令:
// directive-clickoutside.js
export default {
bind(el, binding, vnode) {
el.event = function (event) {
// here I check that click was outside the el and his childrens
if (!(el == event.target || el.contains(event.target))) {
// and if it did, call method provided in attribute value
vnode.context[binding.expression](event);
}
};
document.body.addEventListener('click', el.event)
},
unbind(el) {
document.body.removeEventListener('click', el.event)
},
};
// main.js
import clickout from 'utils/directive-clickoutside';
Vue.directive('clickout', clickout);
我在我的组件模板中使用了它:
// HeaderSubmenu component
<template>
<li class="header-submenu">
<!-- élément du header servant à ouvrir le sous-menu -->
<header-link v-bind="$props" :href="to ? false : '#'" @click.native="toggle()">
<slot name="item"></slot>
</header-link>
<!-- sous-menu -->
<ul class="submenu-list" :class="{'open': open, 'animated': animated}" @animationend="displaynone()" v-clickout="hide()">
<slot></slot>
</ul>
</li>
</template>
但是当我点击页面上的任何地方时,此代码失败:
Uncaught TypeError: n.context[e.expression] is not a function
at HTMLBodyElement.t.event (directive-clickoutside.js:7)
问题出在哪里?
答案 0 :(得分:4)
问题出在这里。
v-clickout="hide()"
有效的做法是将v-clickout
设置为hide()
的结果。相反,只需将hide
方法传递给它。
v-clickout="hide"
一般情况下,对于Vue,在模板中,如果您只是想让模板调用函数而不做任何特殊操作,只需将函数名称传递给它。