Vue.js - 从指令发出事件 [英] Vue.js - Emit event from directive

查看:38
本文介绍了Vue.js - 从指令发出事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以从指令附加该指令的组件发出自定义事件.

Is it possible to emit a custom event from the directive in the component to which this directive is attached.

我希望它像示例中描述的那样工作,但它没有.

I was expecting it to work as described in example, but it does not.

示例:

//Basic Directive
<script>
  Vue.directive('foo', {
    bind(el, binding, vnode) {
      setTimeout(() => {
        //vnode.context.$emit('bar'); <- this will trigger in parent
        vnode.$emit('bar');
      }, 3000);
    }
  });
</script>


//Basic Component
<template>
  <button v-foo @bar="change">{{label}}</button>
</template>
<script>
  export default{
    data() {
      return {
        label: 'i dont work'
      }
    },
    methods: {
      change() {
        this.label = 'I DO WORK!';
      }
    }
  }
</script>

对此事有什么想法吗?我错过了什么吗?

Any ideas on the matter? Am I missing something?

JSFiddle:https://jsfiddle.net/0aum3osq/4/

更新 1:

好的,我发现如果我调用 vnode.data.on.bar.fn();(或最新 Vue 版本中的 fns())指令它将触发 bar 事件处理程序.

Okay, i've found that if I call vnode.data.on.bar.fn(); (or fns() in latest Vue versions) in directive it will trigger bar event handler.

更新 2:

临时解决方案:

  /*temp. solution*/
  var emit = (vnode, name, data) => {
    var handlers = vnode.data.on;

    if (handlers && handlers.hasOwnProperty(name)) {
      var handler = handlers[name];
      var fn = handler.fns || handler.fn;

      if (typeof fn === 'function') {
        fn(data);
      }
    }
  } 

//Basic Directive
<script>
  Vue.directive('foo', {
    bind(el, binding, vnode) {
      setTimeout(() => {
        emit(vnode, 'bar');
      }, 3000);
    }
  });
</script>

推荐答案

所以我在 Vue 2+ 中使用的解决方案(考虑到目前还没有答案):

So the solution I am using in Vue 2+ (considering there were no answers so far):

在指令中添加方法:

var emit = (vnode, name, data) => {
  var handlers = (vnode.data && vnode.data.on) ||
    (vnode.componentOptions && vnode.componentOptions.listeners);

  if (handlers && handlers[name]) {
    handlers[name].fns(data);
  }
}

这样称呼它:

bind(el, binding, vnode) {
  emit(vnode, 'bar' , {some: 'event', data: 'here'});
}

一种方法的好处:

1 在你的项目中保持相同的代码风格,这意味着每个处理程序都可以声明为
v-on:handler_name 并以有意义的(对于开发人员)方式处理.其他解决方案,例如将回调作为参数发送,如果不深入研究文档/代码,有时会令人困惑且不明显.

1 Keep the same code-style in your project, meaning that every handler can be declared as
v-on:handler_name and be handled in meaningful (for developer) way. Other solutions, like sending callback as parameter, are sometimes confusing and not obvious without digging into documentation/code.

2 使用内置事件系统还可以优雅地处理事件对象.例如,此代码将工作得很好:

2 Using built-in events system also allows to gracefully handle event objects. For example, this code will work perfectly fine:

<button v-foo @bar="bar(1, $event, 2)">{{label}}</button>
...
methods: {
  bar(one, event, two) { console.log(one, event, two); }
} 

<小时>

在 v2.1+ 中,您可以使用内部指令绑定:

In v2.1+ you can use this inside directive binding:

vnode.context.$emit(eventname)

这篇关于Vue.js - 从指令发出事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆