Directiva personalizada de Vue.js que detecta clic fuera del elemento con TypeScript
Estoy tratando de crear una directiva personalizada usando este ejemplo: https://stackoverflow.com/a/42389266/5470563
archivo main.ts:
import Vue from 'vue';
import HeaderNav from './components/HeaderNav.vue'
Vue.directive('click-outside', {
bind: function (el, binding, vnode) {
el.clickOutsideEvent = function (event) {
// here I check that click was outside the el and his childrens
if (!(el == event.target || el.contains(event.target))) {
// and if it did, call method provided in attribute value
vnode.context[binding.expression](event);
}
};
document.body.addEventListener('click', el.clickOutsideEvent)
},
unbind: function (el) {
document.body.removeEventListener('click', el.clickOutsideEvent)
},
});
new Vue({
el: '#app',
components: {
HeaderNav
}
});
Y obtengo un error de compilación:
La propiedad 'clickOutsideEvent' no existe en el tipo 'HTMLElement'.
¿Cómo lo arreglo? ¿O hay alguna mejor solución para vincular eventos al hacer clic fuera del elemento?
Respuesta #1
Tienes 2 opciones
convierte el parámetro el en las funciones bind y unbind a any.
bind: function (el: any, binding, vnode) {
unbind: function (el: any) {
extender la interfaz HTMLElement.
Puedes colocarlo antes de la declaración de la directiva.
interface HTMLElement {
clickOutsideEvent: () => void;
}
Respuesta #2
Aquí hay una implementación que uso actualmente, espero que ayude:
export default {
bind: function(el, binding, vNode) {
// Provided expression must evaluate to a function.
if (typeof binding.value !== "function") {
const compName = vNode.context.name;
let warn = `[Vue-click-outside:] provided expression '${binding.expression}' is not a function, but has to be`;
if (compName) {
warn += `Found in component '${compName}'`;
}
console.warn(warn);
}
// Define Handler and cache it on the element
const bubble = binding.modifiers.bubble;
const handler = e => {
if (bubble || (!el.contains(e.target) && el !== e.target)) {
binding.value(e);
}
};
el.__vueClickOutside__ = handler;
// add Event Listeners
document.addEventListener("mousedown", handler);
},
unbind: function(el, binding) {
// Remove Event Listeners
document.removeEventListener("mousedown", el.__vueClickOutside__);
el.__vueClickOutside__ = null;
}
};Luego registra la directiva en tu archivo principal
// Directives
Vue.directive("click-outside", ClickOutside);