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

javascript - Parent onClick is not triggered when the child element is clicked inside button - Stack Overflow

programmeradmin4浏览0评论

I have a dropdown-button component which has a click lister. The button has some text and icon. The click event is triggered if we click the button carefully on the outline and not on the text or icon. Here is my component:

<template lang="html">
<div>
  <button class="button dropbtn" @click="toggleDropdown">
    <span>{{ name }}</span>
    <span class="icon"><i class="fa fa-caret-down"></i></span>
  </button>
  <div v-show="visible" class="dropdown-content is-primary-important">
    <slot>
    </slot>
  </div>
</div>
</template>

<script>
export default {
  props: ['name'],
  data: function() {
    return {
      visible: false
    }
  },
  mounted: function() {
    this.hideDropdownOnClick();
  },
  methods: {
    toggleDropdown: function() {
      // trigged on click of the button
      // make the dropdown visible
      console.log("toggling dropdown");
      this.visible = !this.visible;
    },
    hideDropdownOnClick: function() {
      window.onclick = (event) => {
        console.log(event.target);
        if (!event.target.matches('.dropbtn')) {
          console.log("here", this.visible);
          this.visible = false;
        }
      }
    }
  }
}
</script>

<style lang="css">
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
  position: absolute;
  background-color: #fff;
  min-width: 140px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

/* Links inside the dropdown */
.dropdown-content a {
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}
</style>

I feel that I am missing something very basic here, can someone help me with this? Thanks.

Edit

It seems like a bug with the browser as the answer to this question says: Button element not firing click event when clicking on button text and releasing off it (but still inside the button)?

I have a dropdown-button component which has a click lister. The button has some text and icon. The click event is triggered if we click the button carefully on the outline and not on the text or icon. Here is my component:

<template lang="html">
<div>
  <button class="button dropbtn" @click="toggleDropdown">
    <span>{{ name }}</span>
    <span class="icon"><i class="fa fa-caret-down"></i></span>
  </button>
  <div v-show="visible" class="dropdown-content is-primary-important">
    <slot>
    </slot>
  </div>
</div>
</template>

<script>
export default {
  props: ['name'],
  data: function() {
    return {
      visible: false
    }
  },
  mounted: function() {
    this.hideDropdownOnClick();
  },
  methods: {
    toggleDropdown: function() {
      // trigged on click of the button
      // make the dropdown visible
      console.log("toggling dropdown");
      this.visible = !this.visible;
    },
    hideDropdownOnClick: function() {
      window.onclick = (event) => {
        console.log(event.target);
        if (!event.target.matches('.dropbtn')) {
          console.log("here", this.visible);
          this.visible = false;
        }
      }
    }
  }
}
</script>

<style lang="css">
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
  position: absolute;
  background-color: #fff;
  min-width: 140px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

/* Links inside the dropdown */
.dropdown-content a {
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}
</style>

I feel that I am missing something very basic here, can someone help me with this? Thanks.

Edit

It seems like a bug with the browser as the answer to this question says: Button element not firing click event when clicking on button text and releasing off it (but still inside the button)?

Share Improve this question edited May 23, 2017 at 10:31 CommunityBot 11 silver badge asked Apr 14, 2017 at 12:17 aksaks 9,49111 gold badges52 silver badges81 bronze badges 4
  • I'm sorry but I don't think I understand what you said. Should the child items return a true onClick? – aks Commented Apr 14, 2017 at 12:22
  • @aks your code is working for me... jsfiddle.net/jwtmL0fd – Happyriri Commented Apr 14, 2017 at 12:29
  • Oops, its vue, I am not aware of the behavior. For js it should be bubble to parent if you are not preventing it by stopPropogation. – Anil Commented Apr 14, 2017 at 12:29
  • @SLYcee it doesn't! please try clicking on the text, in my browser chrome it is not working! – aks Commented Apr 14, 2017 at 12:30
Add a comment  | 

4 Answers 4

Reset to default 19

Adding this CSS rule fixes the issue for me:

span {
    pointer-events: none;
}

When You click in span its toggled twice:) once by toggleDropdown method, second by windows onclick handler.

here is working example: jsfiddle

<template id="tmp">
  <div>
  <button class="button dropbtn" @click="toggleDropdown">
    <span>{{ name }}</span>
    <span class="icon"><i class="fa fa-caret-down"></i></span>
  </button>
  <div v-show="visible" class="dropdown-content is-primary-important">
    <slot>
    </slot>
  </div>
</div>
</template>

<div id="x">
  <tmp name="my name">
     <span>toggle me!</span>
  </tmp>
</div>

Vue.component('tmp', {
template: '#tmp',

props: ['name'],
data: function() {
return {
  visible: false
}
},
mounted: function() {
this.hideDropdownOnClick();
},
methods: {
toggleDropdown: function() {
  // trigged on click of the button
  // make the dropdown visible
  console.log("toggling dropdown");
  this.visible = !this.visible;
}
}
});

new Vue({
el: '#x',
data: function(){
    return {
    name: 'myName'
  }
}
});

edit: if you don't want to use clickaway here is small directive to detect clicks outside of element:

var VueClickOutSide = {

    bind: function(el, binding, vNode) {
        var bubble = binding.modifiers.bubble;
        var handler = function(e) {
            if (bubble || (!el.contains(e.target) && el !== e.target)) {
                binding.value(e);
            }
        }
        el.__vueClickOutside__ = handler;
        document.addEventListener('click', handler);
    },

    unbind: function (el, binding, vNode) {
        document.removeEventListener('click', el.__vueClickOutside__);
        el.__vueClickOutside__ = null;
    }
};

You just have to register that directive:

Vue.directive('click-outside', VueClickOutSide)

And use it in template:

 v-click-outside:delay="hideDropdownOnClick"

You can use vue-clickaway to hide dropdown when click outside :

  1. $ npm install vue-clickaway --save
  2. import { mixin as clickaway } from 'vue-clickaway';

  3. export default { mixins: [ clickaway ], ... the rest of your code ...

  4. You put v-clickaway="visible = false" in your root div of your dropdown-button component.

On click you show and immediately hide list. You click text or icon (they are "span"),

this.visible = !this.visible;

then code goes to window.onclick where

if (!event.target.matches('.dropbtn'))

and your spans dont have this class. So you set

 this.visible = false;

Change check to

    if (!event.target.closest('.dropbtn')) 
发布评论

评论列表(0)

  1. 暂无评论