条件事件绑定 - vuejs

问题描述 投票:4回答:3

在我的场景中,我有鼠标悬停和mouseout事件,我想有条件地绑定(例如,仅当用户在具有鼠标的设备上)。

我意识到我可以在事件处理程序本身中具有条件但是仍然会为事件处理程序分配内存,这是不必要的。

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

(很明显,我想要的是能够使事件订阅短路,因此如果条件为false,则不会发生基础的addEventListener操作)

events vue.js
3个回答
7
投票

this discussion之后,看来实现此目的的最佳方法是将v-on绑定到包含您有兴趣订阅的事件的规范对象,并将条件放在那里:

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

一些说明:

  • 为处理程序传递null意味着底层的addEventLisetener不会发生 - 这就是我们想要的
  • 这意味着将所有事件订阅分组为一个v-on属性,而不是将其拆分为单独的显式绑定(<div @mouseover='...' @click='...'/>
  • 如果这是一个长期存在的组件并且基础数据经常更改(导致重新绑定),那么您应该注意处理订阅(即相应的removeEventListener),因为在一个绑定传递中进行的订阅将不会在后续传递中处理。根据您的用例进行评估......

2
投票

更简单的是使用渲染功能。您无需手动删除侦听器并进行处理。也使用简单的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
    );
  }
});

完整的例子:https://codesandbox.io/s/nw6vyo6knj


1
投票

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

标记

<button ref="button">
  Mouse Over Me
</button>

实例视图

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

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

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

MI信

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

实例视图

new Vue({
  el: '#app',
  mixins: [mouseEvents]
})

标记

<button v-mouse-events>
  Mouse Over Me
</button>

这是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)
      }
    }
});

现在你需要做的就是像使用v-bind一样添加每个监听器:

<div v-mouse:mouseover="mouseOverFunction"></div>

这是JSFiddle向您展示它是如何工作的:https://jsfiddle.net/59ym6hdb/

© www.soinside.com 2019 - 2024. All rights reserved.