添加 eventListener 以模糊自定义组件上的事件?

Posted

技术标签:

【中文标题】添加 eventListener 以模糊自定义组件上的事件?【英文标题】:Adding eventListener to blur event on custom component? 【发布时间】:2018-08-24 23:44:47 【问题描述】:

我有一个名为 styled-input 的组件,它是一个包含样式、图标、验证等的输入。

我正在尝试在自定义指令中使用 addEventListener 来监听事件并让事情发生。

<styled-input
    v-model=""
    v-on:input=""
    v-on:blur=""
></styled-input>

内部: value 是一个道具(允许v-model 绑定在外面)

<template>
    <div>
        <input 
            v-bind:value="value"
            v-on:input="$emit('input', $event.target.value)"
            v-on:blur="$emit('blur', $event.target.value)"
        />
    </div>
</template>

我正在尝试通过自定义指令addEventListeners 对标签进行自定义验证。

<styled-input
    v-model=""
    v-custom-validator:credit-card
></styled-input>

在指令中,我使用addEventListener 来监听来自输入字段的事件。

Vue.directive('custom-validator', 
    bind: function(el, binding) 
        el.addEventListener('blur', (event) => 
            // Does not fire
        );

        el.addEventListener('input', (event) => 
            /// Fires
        );
    ,
);

为什么模糊事件不触发,而输入事件触发?

如何让模糊事件触发?

【问题讨论】:

为什么要强制另一个元素的事件?只调用与之关联的操作不是更干净吗? 【参考方案1】:

为什么模糊失败

您没有选择blur,因为您没有指定useCapture argument。这是强制性的,因为blur event does not bubble。所以添加useCapture 可以解决您的问题:

el.addEventListener('blur', (e) => 
  // it will work now
, true); // useCapture is the third argument to addEventListener

不要将 Native DOM 事件与 Vue 事件混淆

从您的代码(参见下面的演示)中,可能似乎blurinput 被触发时,.addEventListener() 会选择$emit() 发出的内容。 事实并非如此

您可能会明白这一点,因为除了您的v-ons 中的$emit()s 之外,&lt;input&gt;触发原生事件blurinput

所以你实际上有两种不同类型的事件blur 和两种input(见下面的演示)。

$emit() 怎么了?

$emit() 是 Vue 内部的。它是零件或every Vue 实例events interface

.addEventListener() 用于原生 DOM 事件。它会听.dispatchEvent()s,而不是$emit()s。

要收听 Vue 的 $emit()s,您必须使用 Vue 的 .$on()

请参阅下面的演示。请注意.$on().addEventListener() 中的e(事件)对象不同

Vue.component('my-comp', 
  template: '#styled-input-tpl',
  props: ['value']
);

Vue.directive('my-directive', 
  bind: function (el, binding, vnode) 
    vnode.componentInstance.$on('blur', function (e) 
      console.log('received $on(blur) - event value:', event);
    );
    vnode.componentInstance.$on('input', function (e) 
      console.log('received $on(input) - event value:', e);
    );
    
    el.addEventListener('blur', (e) => 
      console.log('received NATIVE(blur) - event value:', e.target);
    , true);  // <======================================================= IMPORTANT
    
    el.addEventListener('input', (e) => 
        console.log('received NATIVE(input) - event value:', e.target);
    );
  
)

new Vue(
  el: '#app'
)
<script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script>

<template id="styled-input-tpl">
    <div>
        <input 
            v-bind:value="value"
            v-on:input="$emit('input', $event.target.value)"
            v-on:blur="$emit('blur', $event.target.value)"
        />
    </div>
</template>

<div id="app">
  Edit the input, focus out, and check the console.
  <my-comp v-my-directive :value="'edit me'"></my-comp>
</div>

【讨论】:

只是对此的后续问题。如何从指令内部访问组件v-model 的当前值? 视情况而定。在组件内部,您无法判断父级使用的是v-model 还是简单的:value(因为v-model 只是:value+@input 的简写/语法糖)。不管怎样,我想你想要的是vnode.componentInstance.$props,是吗? 是的,这正是我想要的。谢啦。最后一个问题,vnode.componentInstance.$on 是否需要手动移除监听器? (就像你对removeEventListener 所做的那样 您可能需要。 API 中还有其他不同的方法可以处理您的用例:$once()$off()。请参阅文档:vuejs.org/v2/api/#Instance-Methods-Events vnode.componentInstance 未在指令中定义 :)

以上是关于添加 eventListener 以模糊自定义组件上的事件?的主要内容,如果未能解决你的问题,请参考以下文章

iView中表格(Table)自定义表头添加模糊搜索框

openstack 权限控制 (添加自定义角色)keystone等组件

模态 VC 和旋转的自定义背景

Spring-自定义事件发布

无法使用 Vue.js 在可重用组件之间添加自定义内容

具有自定义属性表单的 ASP.NET 组件