在Vue.js中收听自定义事件

时间:2016-03-22 14:00:18

标签: javascript vue.js

Vue.js适用于clickmousedown等浏览器事件。但是根本不适用于自定义事件。这是代码:

HTML:

<div id="app" style="display: none" v-show="true">
    <div v-el:ping v-on:ping="ping">
        <div>
            <button v-on:click="click">Click</button>
        </div>
    </div>
</div>

JavaScript的:

new Vue({
    el: '#app',
    data: {
    },
    methods: {
        ping: function (event) {
            console.log('Vue ping', event);
            alert('Vue ping');
        },
        click: function (event) {
            jQuery(event.target).trigger('ping');
        }
    },
    ready: function () {
        console.log(this.$els);
        jQuery(this.$els.ping).on('ping', function (event) {
            console.log('jQuery ping', event);
            alert('jQuery ping');
        });
    }
});

我希望Vue pingjQuery ping提醒您。但只有后来弹出。

CodePen

3 个答案:

答案 0 :(得分:10)

Vue拥有自己的内部system for custom events,您应该使用它而不是jQuery / native DOM事件:

click: function (event) {
  // jQuery(event.target).trigger('ping');

  this.$dispatch('ping', event.target) // send event up the parent chain, optionally send along a reference to the element.

  // or:
  this.$emit('ping') // trigger event on the current instance
}

编辑:$ dispatch用于父子通信,您似乎想要从同一个组件中触发自定义事件。在这种情况下,您可以简单地调用方法。

如果您仍想在同一组件中收听自定义事件,请执行以下操作:

  1. 想要使用$ emit
  2. 在模板中不能使用v-on:custom-event-name(仅用于组件)。而是将事件方法添加到events:

    事件:{   ping:function(){....} }

答案 1 :(得分:2)

这是在香草JS:

HTML:

<div id="app">
  <div v-el:ping>
    <div>
      <button v-on:click="click">Click</button>
    </div>
  </div>
</div>

JS:

(function() {

  new Vue({
    el: '#app',
    data: {
      event: null
    },
    methods: {
      ping: function(event) {
        alert('Vue ping');
      },
      click: function(event) {
        this.$els.ping.dispatchEvent(this.event);
      }
    },
    ready: function() {
      this.event = document.createEvent("HTMLEvents");
      this.event.initEvent("ping", true, true);
      this.$els.ping.addEventListener('ping', this.ping);
    }
  });

})();

笔:http://codepen.io/anon/pen/wGdvaV?editors=1010#0

答案 2 :(得分:2)

你应该避免混合dom事件和vue组件相关的事件,因为它是不同的抽象层。

无论如何,如果你仍然想这样做,我认为你需要在vue-component实例中缓存this.el或者通过像这样的computed-property获取它

{
    computed : {
        jqueryEl(){ return $(this.el) }
    }
}

然后按this.jqueryEl.trigger('ping')触发自定义jQuery事件。

确保妥善保管元素的绑定是最新的! 例如,您可以动态绑定jQuery事件(并且还可以在组件销毁时取消绑定!),如下所示:

 ready : function(){
    jQuery('body').on('ping.namespace', '[data-jquery="ping"]', function(){ ... })
 },
 destroy : function(){
      jQuery('body').off('ping.namespace')
 }

并且不要忘记将属性[data-jquery="ping"]添加到您想要响应ping事件的元素。

希望这些信息可以帮助您实现预期的结果。