2017-06-17 51 views
1

我有一個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">

我想到了一個全球性事件總線在我的下拉菜單應該是「registred」和檢測上我的應用程序在全球@單擊事件。如果註冊的菜單不是單擊的元素,我們會調用他的toggleMenu()方法。 (理想情況下,我可以註冊其他具有相同行爲的元素。)

...但我根本不掌握vue事件系統。 如何檢查事件是否不在某個元素上? 我不知道如何做到這一點。你可以幫我嗎 ?謝謝 !

======編輯======

隨着我用這個自定義指令伯特·埃文斯的幫助:

// 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) 

問題出在哪裏?

+1

[檢測點擊外部元素](https://stackoverflow.com/questions/36170425/detect-click-outside-element) – Bert

+0

可能的重複感謝,我試圖使用自定義指令,但它以無限更新循環。我編輯了這篇文章向你展示。 – Thaledric

+0

'toggleMenu'做什麼? – Bert

回答

2

問題就在這裏。

v-clickout="hide()" 

你正在做的是設置v-clickouthide()結果有效的。相反,只需傳遞hide方法即可。

v-clickout="hide" 

一般與Vue的,在你的模板,如果你只是想模板調用一個函數,而不是做什麼特別的,只是通過它的函數的名稱。

+0

哦,是的,所以它不像事件指令!我在click事件上添加了「stop」修飾符。 謝謝! 我有最後一個問題:如果我有兩個子菜單,當我打開第一個並打開另一個時,第一個不關閉(當然是因爲切換按鈕的停止修改)。我怎樣才能做到這一點? – Thaledric

+0

@Thaledric首先,事件指令是相同的。您可以將它們設置爲不帶圓括號的名稱。在第二種情況下,我很難想象這種情況。這些真正的子菜單(菜單的子菜單)?也許一個新的問題,所以你可以給所有的細節。 – Bert

+0

謝謝!我在這裏發佈了一個新問題:https://stackoverflow.com/questions/44613980/close-all-popups-when-the-user-click-to-open-a-new-one – Thaledric

相關問題