当子元素在按钮内被点击时,父级的onClick事件不会被触发。

4

我有一个下拉按钮组件,它有一个点击监听器。该按钮包含文本和图标。点击事件仅在我们小心地在轮廓上而不是在文本或图标上单击按钮时触发。这是我的组件:

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

我感觉我在这里缺少一些非常基础的东西,有人能帮帮我吗?谢谢。

编辑

似乎是浏览器的一个错误,这个问题的答案如下: 点击按钮文本并释放仍然在按钮内时,按钮元素不会触发点击事件?


抱歉,我不确定我理解你的意思。子项是否应该返回一个 true onClick? - aks
@aks,你的代码对我来说可行... https://jsfiddle.net/jwtmL0fd/ - Happyriri
哎呀,这是Vue啊,我不熟悉这个行为。对于JavaScript来说,如果你没有使用stopPropagation来阻止冒泡的话,它应该会冒泡到父级元素。 - Anil
@SLYcee,它不起作用!请尝试在文本上单击,在我的浏览器chrome中它无法工作! - aks
4个回答

18

添加以下CSS规则可以解决该问题:

span {
    pointer-events: none;
}

4
这绝对是最简单且最有效的答案。谢谢。 - Doug
3
另一个经典的例子是,被接受的答案比简单解决方案要复杂得多。 - Davis

3
当您在span中单击时,它会被切换两次:一次是通过toggleDropdown方法,另一次是通过窗口的onclick处理程序。
这里是一个可工作的示例: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'
  }
}
});

编辑:如果您不想使用Clickaway,这里有一个小指令可以检测元素外的点击:

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

您只需要注册该指令:
Vue.directive('click-outside', VueClickOutSide)

并将其用于模板:

 v-click-outside:delay="hideDropdownOnClick"

是的,你说得对。你能否提供一种方法,当我们点击外部时,下拉菜单可以隐藏? - aks
正如SLYcee所提到的,您可以使用clickaway。 - donMateo

1

当点击外部时,您可以使用vue-clickaway来隐藏下拉菜单:

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

  3. export default { mixins: [ clickaway ], ... 其余代码 ... }

  4. 您需要在dropdown-button组件的根div中放置v-clickaway="visible = false"


0

点击后,您可以显示并立即隐藏列表。 您可以单击文本或图标(它们是“span”)。

this.visible = !this.visible;

然后代码进入window.onclick,其中

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

而且你的跨度没有这个类。所以你设置

 this.visible = false;

将 check 改为

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接