条件事件绑定-vuejs

asi*_*asi 12 events vue.js

在我的情况我有鼠标悬停及移出的事件,我想结合有条件地(例如,只有当用户是具有鼠标的设备上)。

我知道我可以在事件处理程序本身的条件,但将仍然可以分配的事件处理程序是不必要的内存。

有没有办法使事件绑定本身成为条件?

(很清楚,我想要的是能够使事件订阅短路,以便在条件为false时基础的addEventListener操作永远不会发生)

Eng*_*ici 17

这是我正在使用的:

v-on="condition ? { click: handler } : {}"参考

我得到Invalid handler for event "click": got nullv-on="{ click: condition ? handler : null }"


asi*_*asi 9

在进行了此讨论之后,看来实现此目标的最佳方法是将v-on绑定到包含您感兴趣的事件的规范对象,并将条件放在此处,如下所示:

<div v-on="{ mouseover: condition ? handler : null, click: ... }">

一些注意事项:

  • 为处理程序传递null意味着底层addEventLisetener不会发生-这就是我们想要的
  • 这意味着将所有事件订阅分组为一个v-on属性,而不是将其拆分为单独的显式绑定(<div @mouseover='...' @click='...'/>

  • 如果这是一个寿命很长的组件,并且基础数据经常更改(导致重新绑定),则您应注意对订阅(即对应的removeEventListener)的处理,因为在一次绑定通过中进行的订阅将不会在后续绑定中被处理。根据您的用例进行评估...

  • 进行条件事件绑定的新方法:`v-on="condition ? { mouseover: handler } : {}"` [来自答案中链接的对话](https://github.com/vuejs/vue/issues /7349#issuecomment-380431978) (3认同)

Hea*_*odi 9

如果您收到“事件“click”的无效处理程序:获取 null”错误,并且您的处理程序函数需要一些参数,那么您应该将处理程序包装在函数中。

所以这个>

v-on="condition ? { blur: () => handler(params) } : {}"
Run Code Online (Sandbox Code Playgroud)

代替

v-on="condition ? { click: handler(params) } : {}"
Run Code Online (Sandbox Code Playgroud)


Mar*_*ese 7

从Vue 2.6起可以使用:

<div
  @mouseover="enableMouseover ? mouseoverHandler : null"
  @click="enableClick ? clickHandler : null"
  ...
>
Run Code Online (Sandbox Code Playgroud)

事件解析为时null,绑定将被删除。

https://github.com/vuejs/vue/issues/7349#issuecomment-458405684

  • 将 `@click` 绑定到 `null`,现在会从 Vue 返回警告:`[Vue warn]: Invalid handler for event "click": got null`。 (2认同)

And*_*anu 5

更简单的是使用渲染函数。您不需要手动删除侦听器并处理它们。还使用简单的 JS 语法,没有 mixins。

new Vue({
  el: "#app",
  data: () => ({
    counter: 0
  }),
  methods: {
    handleClick() {
      this.counter++;
    }
  },
  render(h) {
    return h(
      "div",
      IS_MOBILE_DEVICE
        ? {}
        : {
            on: { click: this.handleClick }
          },
      this.counter
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

完整示例: https: //codesandbox.io/s/nw6vyo6knj


小智 5

我无法对答案发表评论,因此我添加了自己的答案。

已批准答案中的解决方案 3不起作用 - 缺少括号。在这种情况下,正确的语法是:

@click="enableClick && clickHandler()"
Run Code Online (Sandbox Code Playgroud)

这是工作示例


cra*_*g_h 4

如果您想做类似的事情,您可以通过在要应用事件的ref上添加 来手动应用事件侦听器,然后在满足条件时element使用它在挂钩中绑定事件侦听器:mounted

标记

<button ref="button">
  Mouse Over Me
</button>
Run Code Online (Sandbox Code Playgroud)

Vue实例

new Vue({
  el: '#app',
  mounted() {
    let hasMouse = true;

    // If the user has a mouse, add the event listeners
    if (hasMouse) {
      let button = this.$refs.button

      button.addEventListener('mouseover', e => {
        this.mouseover = true
      })

      button.addEventListener('mouseout', e => {
        this.mouseover = false
      })
    }

  },
  data: {
    mouseover: false
  }
})
Run Code Online (Sandbox Code Playgroud)

这是一个 JSFiddle:https: //jsfiddle.net/0fderek6/

如果您不喜欢这种方法,您也可以使用 adirective并将条件放在那里,然后您可以将其放置在 a 中mixin以使其可重用:

米辛

const mouseEvents = {
  directives: {
    mouseEvents: {
      bind(el, binding, vnode) {
        let hasMouse = true;

        if (hasMouse) {
          el.addEventListener('mouseover', e => {
            vnode.context.mouseover = true
          })

          el.addEventListener('mouseout', e => {
            vnode.context.mouseover = false
          })
        }
      }
    }
  },
  data: {
    mouseover: false
  }
}
Run Code Online (Sandbox Code Playgroud)

Vue实例

new Vue({
  el: '#app',
  mixins: [mouseEvents]
})
Run Code Online (Sandbox Code Playgroud)

标记

<button v-mouse-events>
  Mouse Over Me
</button>
Run Code Online (Sandbox Code Playgroud)

这是 JSFiddle:https: //jsfiddle.net/nq6x5qeq/

编辑

如果您喜欢这种directive方法,您需要做的就是添加一个unbind钩子来删除侦听器,然后您可以将其binding arg作为事件类型并作为binding value处理程序:

Vue.directive('mouse', {
  bind(el, binding) {
      if (hasMouse) {
        console.log(binding.arg + ' added')
          // bind the event listener to the element
        el.addEventListener(binding.arg, binding.value)
      }
    },
    unbind(el, binding) {
      if (hasMouse) {
        console.log(binding.arg + ' removed')
        el.removeEventListener(binding.arg, binding.value)
      }
    }
});
Run Code Online (Sandbox Code Playgroud)

现在您需要做的就是添加每个侦听器,就像使用以下命令一样v-bind

<div v-mouse:mouseover="mouseOverFunction"></div>
Run Code Online (Sandbox Code Playgroud)

这是 JSFiddle 向您展示其工作原理:https ://jsfiddle.net/59ym6hdb/