回车 触发 button重复点击的解决方案

540 阅读2分钟

问题:

最近遇到一个问题,在vue中的按钮点击之后出现弹框,如果此时不做任何鼠标操作,直接回车,会出现不断调用点击事件,也导致不断出发dialog的初始化,特别dialog有些初始化比较大的时候,更容易发现问题。 原因可以查看HTML: The Living Standard

Keyboard events are always targeted at this focused element.

现象:

这个不仅在vue或者element中会出现,原生的也有这个情况,具体原因未深究,有明白的可以评论区科普一下

解决思路:

首先说一下,本文主要讲解在vue中的处理思路。

image.png 根据上图,分别讨论:

1.解决问题发生的源头

其实大多数页面是无感的,只有部分页面会因为重复点击引出问题,所以可以直接在部分有问题的页面,禁用enter回车事件:

document.onkeydown = (e) => {
    if (e.keyCode === 13) {
        return false;
    }
};

2.判断事件类型

我们可以在点击事件中拿到event,根据eventtype字段来进行处理(点击事件的typeclick,回车的typekeydown):

function handle(e) {
    if (e.type === 'click') {
        // do 
    }
}

3.主动取消焦点

上面的图可以看到,即然回车的时候是根据是否有焦点,那我直接在点击之后,取消按钮的焦点不就OK了吗,这个也有三个思路:

3.1 焦点被抢走

通过点击事件之后,主动让其他元素获取焦点,来达到按钮失焦的效果

常见的思路是设置一个input(可以设置长宽不可见,或者直接移到屏幕外面),每次点击时来获取焦点即可

3.2 主动失焦

顾名思义,在按钮中主动的调用oblur方法达到失焦的效果:

function handle(e) {
    if (e.type === 'click') {
        // do
        
        // 这里的targe 可能要判断好,如果button中包裹的还有其他dom,此时的target不是button,所以要转换成button
        e.target.blur();
    }
}

3.3 优化

上面的写法,觉得有点粗鲁了,所以想用vue的指令来优化一下:

export default function (Vue) {
    let Fun = function (el, binding, vnode) {
        el.addEventListener('click', function (event) {
            el.blur();
        });
    };
    // after-click-blur 简称 abc
    Vue.directive('acb', {
        componentUpdated: Fun
    });
};

// 调用

<el-button
    v-acb
    @click="test"
>
    测试
</el-button>

这里利用了el.addEventListener不会覆盖原方法的特性,只是追加了一个click方法,在点击的时候均会触发,所以每次都正好能够失焦。

总结

好活当赏,求赞

如有误,欢迎指正