添加 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>
我正在尝试通过自定义指令addEventListener
s 对标签进行自定义验证。
<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 事件混淆
从您的代码(参见下面的演示)中,可能似乎当blur
和input
被触发时,.addEventListener()
会选择$emit()
发出的内容。 事实并非如此。
您可能会明白这一点,因为除了您的v-on
s 中的$emit()
s 之外,<input>
将也触发原生事件blur
和input
。
所以你实际上有两种不同类型的事件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 以模糊自定义组件上的事件?的主要内容,如果未能解决你的问题,请参考以下文章