最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin1浏览0评论

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; }
}

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; }
}
Share Improve this question asked Dec 20, 2016 at 23:27 Konrad VilterstenKonrad Viltersten 39.3k84 gold badges286 silver badges509 bronze badges 6
  • try Event-Modifiers, does :click.stop helps? – Saurabh Commented Dec 22, 2016 at 3:10
  • @saurabh The hint was very interesting because it linked to something new to me. However, setting .stop on the click, didn't do much difference. I believe it's a bug. What do you think? – Konrad Viltersten Commented Dec 22, 2016 at 19:30
  • 1 @saurabh Just to clarify. The problem isn't that the inner ponents propagate the click event up to the main menu. In fact, the inner ponents don't have a click event on them at all (except for the implicit event for anchors). I can't put .stop there because then don't have v-on:click to begin with... – Konrad Viltersten Commented Dec 22, 2016 at 22:16
  • I am not sure whether this is a bug or not, doesn't on click event will be applicable on all child elements? Shouldn't you put v-on:click event on <a> item, like this: <a href="#demo" class="nav-link dropdown-toggle" v-on:click="clickMenu">DEMO</a> if this is needed only on that on not on inside <u> – Saurabh Commented Dec 24, 2016 at 5:49
  • @saurabh I'm starting to believe that you're right. My question should be rather how to make the clicketty click to only be allowed on the top parent but that's doable using markup changes. So you kind of answered my question anyway. Why don't you post it as a reply so I can accept it? – Konrad Viltersten Commented Dec 24, 2016 at 18:54
 |  Show 1 more ment

1 Answer 1

Reset to default 9

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 es 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 ponent 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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>