blur 事件

阻止 blur 事件

日常开发中经常会有这样的需求:

  1. 输入框聚焦,且有已输入字符时,显示关闭按钮
  2. 输入框失焦,不显示关闭按钮
  3. 点击关闭按钮,清空输入

根据以上要求,实现的结果为:

可以发现,第 1 和 2 条已经实现,但 第 3 条实现存在问题:点击清空按钮时,输入框的内容并没有清空。

代码实现如下:

<template>
    <div class="stop-blur">
        <input
            v-model="input"
            type="text"
            class="input"
            @blur="handleBlur"
            @focus="handleFocus"
        >
        <i
            v-show="isClearIconVisible"
            class="clear-icon"
            @click="clear"
        >×</i>
    </div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from 'vue';
export default defineComponent({
    setup() {
        const input = ref('');
        const isInputFocus = ref(false);
        const isClearIconVisible = computed(() => {
            return isInputFocus.value && input.value.length > 0;
        });

        return {
            input,
            isClearIconVisible,
            handleBlur() {
                isInputFocus.value = false;
            },
            handleFocus() {
                console.log('focus');
                isInputFocus.value = true;
            },
            clear() {
                input.value = '';
            }
        };
    }
});
</script>

<style lang="less" scoped>
.stop-blur {
    position: relative;
    display: flex;
    width: 300px;
    font-size: 16px;
    line-height: 40px;
    input {
        flex: 1;
        height: 40px;
        padding: 0 45px 0 5px;
        border-radius: 4px;
        border: 1px solid #DCDFE6;
        background-color: #FFF;
        box-sizing: border-box;
        outline: 0;
    }
    i {
        flex: none;
        position: absolute;
        top: 0;
        right: 0;
        width: 40px;
        height: 40px;
        text-align: center;
        font-style: normal;
        cursor: pointer;
    }
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

究其原因,点击.clear-icon时,会先触发.inputblur事件导致.clear-icon元素先消失,因此.clear-icon元素并没有触发click事件。

要想解决这个问题,只需阻止.clear-icon元素的mousedown事件的默认行为。

<i
    v-show="isClearIconVisible"
    class="clear-icon"
    @mousedown.prevent
    @click="clear"
>×</i>
1
2
3
4
5
6

修复后的效果:

原理解释:当点击.clear-icon元素时会先触发它的mousedown事件,而mousedown事件的默认行为就是使当前点击元素之外的有焦点的元素失去焦点,如果阻止.clear-icon元素的mousedown事件的默认行为,就能阻止.input元素失去焦点,.clear-icon元素就不会消失,也能触发click事件了。