检测点击元素外部

30 浏览
0 Comments

检测点击元素外部

在Vue.js中,如何检测点击事件发生在元素之外?我知道在原生的JavaScript中可以这样做,但是在使用Vue.js时是否有更合适的方法呢?\n这是原生JavaScript的解决方案:Javascript Detect Click event outside of div\n我猜应该有更好的方法来访问这个元素吧?

0
0 Comments

Detect click outside element(检测点击元素外部)这个问题的出现的原因是希望在Vue 1中实现点击元素外部时触发特定事件的功能。解决方法是通过设置自定义指令来实现。

解决方法的具体实现如下:

首先,在Vue中设置一个名为`click-outside`的自定义指令。在`bind`阶段,绑定事件监听器,监听元素的点击事件,并通过`this.stopProp`方法阻止事件冒泡。同时,在`bind`阶段还通过`document.body`监听整个文档的点击事件,并触发自定义事件。在`unbind`阶段,解绑事件监听器。

代码如下:

Vue.directive('click-outside', {
  bind () {
      this.event = event => this.vm.$emit(this.expression, event)
      this.el.addEventListener('click', this.stopProp)
      document.body.addEventListener('click', this.event)
  },   
  unbind() {
    this.el.removeEventListener('click', this.stopProp)
    document.body.removeEventListener('click', this.event)
  },
  stopProp(event) { event.stopPropagation() }
})

使用方法如下:

在组件中,使用`v-click-outside`指令,并传入自定义事件名。

Some content

在组件中,通过`events`选项监听自定义事件,并在事件处理函数中执行相应操作。

events: {
  nameOfCustomEventToCall: function (event) {
    // do something - probably hide the dropdown menu / modal etc.
  }
}

如果想要了解更多关于此解决方法的信息,可以查看JSFiddle上的演示和注意事项。

演示地址:https://jsfiddle.net/Linusborg/yzm8t8jq/

另外,使用`v-show`指令也是一种选择,并且更加简单,可以达到相同的效果。例如,可以通过`v-show="hide"`来实现点击元素外部隐藏元素的功能,其中`hide`是一个方法,用于设置`isActive`属性为`false`。


有用户尝试在Vue 1中使用这种解决方法,但是发现即使在组件本身点击也会触发事件。用户希望知道是否有解决这个问题的方法。

0
0 Comments

在开发中,有时候我们需要检测点击元素外部的事件,例如当点击某个特定的元素以外的区域时,执行一些操作。下面是一种解决方案。

首先,在组件中添加tabindex属性,使其能够获取焦点,并进行如下操作:

<template>
    <div
        class="handleFocus"
        @focus="handleFocus"
        @focusout="handleFocusOut"
        tabindex="0"
    >
      // 在这里放置一些内容
    </div>
</template>
<script>
export default {    
    methods: {
        handleFocus() {
            // 在这里执行一些操作
        },
        handleFocusOut() {
            // 在这里执行一些操作
        }
    }
}
</script>

另外,如果你不想在点击元素时出现高亮框,可以将tabindex设置为-1,这样可以使

元素成为可聚焦的,但不会出现高亮框。

如果tabindex为-1时无法隐藏高亮框,可以在元素的focus事件中添加outline: none;样式。

如果我们想将这个解决方案应用到一个滑动显示在屏幕上的侧边导航栏中,我们可以在点击侧边导航栏时给它设置焦点。可以使用tabindex="-1",这样当你按下Tab键时,不会自动获取焦点。

某些情况下,这种方法在他的情况下只在首次触发时调用了focusout事件,有没有解决办法呢?

可以在显示组件时,通过编程方式触发焦点。例如,当点击另一个组件来激活弹出菜单组件时,菜单组件可以调用自己的show()方法,然后在其根

元素上调用focus()方法。这样,当用户点击屏幕上根

元素以外的任何地方时,focusout事件将被调用。

另外,你可以通过添加一个ref,如<div ref="menuOptions">,然后在组件的mounted()钩子函数中给它设置焦点this.$refs.menuOptions.focus();,这样可以在点击外部元素时捕获事件,而无需先设置焦点。

还有一个问题是,当点击聚焦元素内部的子元素时,会触发focusout事件。

我找到了解决办法。为了防止点击子元素导致父元素关闭,可以在事件回调函数中加入条件判断:if(!event.currentTarget.contains(event.relatedTarget)) { }。这样只有在点击元素外部时,才会执行相应的操作。

0
0 Comments

在使用vue.js 2.0时,我使用了以下解决方案,该解决方案基于Linus Borg的回答,可以很好地工作。

Vue.directive('click-outside', {

bind: function (el, binding, vnode) {

el.clickOutsideEvent = function (event) {

// 在这里检查点击是否在el及其子元素之外

if (!(el == event.target || el.contains(event.target))) {

// 如果是,则调用属性值中提供的方法

vnode.context[binding.expression](event);

}

};

document.body.addEventListener('click', el.clickOutsideEvent)

},

unbind: function (el) {

document.body.removeEventListener('click', el.clickOutsideEvent)

},

});

使用v-click-outside进行绑定:

这里有一个小的演示:

Here's a small demo

您可以在https://v2.vuejs.org/v2/guide/custom-directive.html#Directive-Hook-Arguments中找到有关自定义指令以及el、binding、vnode代表的更多信息。

在Vue 2.0中,工作正常,但指令不再具有实例,因此这是未定义的。解决方法是将“this”替换为“el”以将事件绑定到元素上。

这可能是因为窗口作为“this”传递。我已经修复了这个错误。感谢您指出这个错误。

如果您想要在元素之外检测左键和右键单击怎么办?您还会在contextmenu上添加一个监听器吗?

我认为click既是左键又是右键的事件。

您好。我已经在webpackBin中实现了您的答案,但在组件挂载之前,点击按钮时函数clickOutside被调用,您能帮忙解释一下为什么吗?

有没有办法排除特定的元素?例如,我有一个在元素之外的按钮,点击该按钮会打开此元素,但由于触发了两种方法,所以没有任何反应。

el.event是什么?

您能解释一下vnode.context[binding.expression](event)是什么意思吗?

这对我来说只能部分工作(不确定是否与浏览器有关,但我正在使用IE 11,无法测试其他浏览器)。问题在于它不适用于位于body结束标签下面的空白处。因此,我使用了vue-clickaway提到的解决方法。

如何更改这样,以便可以在v-click-outside中使用表达式而不是方法触发?

如何在Vue组件内使用这个(我正在使用Vue CLI 3)?

el == event.target是多余的。el.contains(event.target)检查给定的节点(event.target)是否是节点本身(el)或其子节点之一。除此之外,解决方案很好。

这个方法工作得很完美。但是当我使用vue-datepicker等插件时,在选择日期时会触发外部点击。有解决方法吗?

如果您希望按钮或菜单外部的其他元素不触发指令回调,您可以像这样做:if (event.target.id !== 'myButton' && !(el == event.target || el.contains(event.target))) { ... }

@Žilvinas 是的,只需在切换按钮上执行event.stopPropagation()。

对于绝对定位的元素的子元素,这个指令不起作用。

这个指令的代码需要添加到main.js文件中。

0