Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue spreads the @click attribute to all its children, which is unexpected and weird

I've set up this menu. Then, I have the methods openMenu, closeMenu and clickMenu.

<li class="nav-item dropdown" 
  v-on:mouseenter="openMenu" 
  v-on:mouseleave="closeMenu" 
  v-on:click="clickMenu">

  <a href="#demo" class="nav-link dropdown-toggle">DEMO</a>
  <ul class="dropdown-menu">
    <li class="dropdown-item"><a href="#">Demo 1</a></li>
    <li class="dropdown-item"><a href="#">Demo 2</a></li>
  </ul>
</li>

When I investigated what's going on, I noticed that clicking and mousing the main menu works as expected to. However, it seems that the anchors from the submenu also react to a click event. I haven't set any listeners to them in other locations. In fact, when I remove the @click form the top one, the submenus stop registering a click.

So it's definitely that the daddy menu spreads the even listening to the children! So unexpected...

Then, I tried the other events. And wouldn't you know? Those behave exactly as expected. No spreading of the hovering event at all.

Is this a bug? How to report it?

(If it's a feature then it's one of the most stupid ones ever.)

I know it doesn't matter but I can bet my donkey that someone as stunned as me will assume it's something super basic and ask for the code to the scripts. The issue is not there but since I'm such a flexible guy, here it is.

methods: {
  openMenu: (event) => { debugger; },
  closeMenu: (event) => { debugger; },
  clickMenu: (event) => { debugger; }
}
like image 409
Konrad Viltersten Avatar asked Dec 20 '16 23:12

Konrad Viltersten


People also ask

How do I prevent a parent's onclick event from firing when a child anchor is clicked?

Use stopPropagation method, see an example: $("#clickable a"). click(function(e) { e. stopPropagation(); });

How emit works in Vue?

Using emit , we can trigger events and pass data up the component heirarchy. This is useful for things like: emitting data from an input. closing modals from inside the modal itself.

What is$ emit in Vuejs?

While It is strongly advised that you record all events emitted by each of your components. Vue $emit is a function that lets us emit, or send, custom events from a child component to its parent.


1 Answers

If there are two elements element 1 and element 2 . element 2 is inside element 1 and we attach an event with both the elements lets say onClick. Now when we click on element 2 then eventHandler for both the elements will be executed. Now here the question is in which order the event will execute. If the event attached with element 1 executes it is called event capturing and if the event attached with element 2 executes first this is called event bubbling. As per W3C the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling

You can find nice explanation here and What is event bubbling and capturing?. There are already questions on Child element click event trigger the parent click event.


In your case, you can try using vue event modifiers, there are .stop and .capture, which might help or you can put the onclick event only on relevant component as well, like this:

<li class="nav-item dropdown">
  <a href="#demo" class="nav-link dropdown-toggle"   
     v-on:mouseenter="openMenu" 
     v-on:mouseleave="closeMenu" 
     v-on:click="clickMenu">DEMO</a>
  <ul class="dropdown-menu">
    <li class="dropdown-item"><a href="#">Demo 1</a></li>
    <li class="dropdown-item"><a href="#">Demo 2</a></li>
  </ul>
</li>

Try using .v-on:click.self, as the documentation says

only trigger handler if event.target is the element itself i.e. not from a child element

like image 67
Saurabh Avatar answered Oct 17 '22 10:10

Saurabh