【问题标题】:Vue.js custom directive detecting click outside element with TypeScriptVue.js 自定义指令使用 TypeScript 检测点击外部元素
【发布时间】:2020-08-27 01:42:24
【问题描述】:

我正在尝试使用此示例创建自定义指令:https://stackoverflow.com/a/42389266/5470563

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
        }
});

我得到一个编译错误:

“HTMLElement”类型上不存在属性“clickOutsideEvent”。

我该如何解决?或者有没有更好的解决方案来绑定外部元素点击事件?

【问题讨论】:

    标签: typescript vue.js vuejs2


    【解决方案1】:

    你有两个选择

    bindunbind 函数中的el 参数转换为any

    bind: function (el: any, binding, vnode) {
    unbind: function (el: any) {
    
    

    扩展HTMLElement接口。

    你可以把它放在指令声明之前。

    interface HTMLElement {
      clickOutsideEvent: () => void;
    }
    

    【讨论】:

    • 编译现在运行良好,但单击任意位置后出现 JS 错误:Uncaught TypeError: vnode.context[binding.expression] is not a function at HTMLBodyElement.el.clickOutsideEvent
    • 哦,这是因为我没有将函数定义为 v-click-outside 自定义指令的属性。谢谢!
    【解决方案2】:

    这是我目前使用的一个实现,希望对您有所帮助:

    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;
      }
    };

    然后在你的主文件中注册指令

    // Directives
    Vue.directive("click-outside", ClickOutside);

    【讨论】:

    • OP 有打字稿错误,他的 javascript 代码看起来不错。
    • 只是建议我以前使用的解决方案,以防万一这个解决方案不起作用。
    猜你喜欢
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    • 2020-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    相关资源
    最近更新 更多