踩坑 - click事件与blur事件冲突问题 & input文件上传同名文件问题

click事件与blur事件冲突问题

click事件与blur事件

  • blur事件: 表单事件,元素失去焦点时候触发,不会冒泡;
  • click事件: 当点击元素的时候触发,所有元素均有此事件,会冒泡;

    注意:

    除了focus和blur事件,其他的表单事件均会冒泡。

问题的提出

当点击某个元素导致前一个元素失去焦点的时候,blur事件会先于click事件触发。

1
2
3
4
5
6
7
8
9
document.querySelector('#ipt').addEventListener('blur', () => {
console.log('blur');
});
document.querySelector('#btn').addEventListener('click', () => {
console.log('click');
});
// blur
// click

解决方法

1. 延迟执行blur事件

1
2
3
4
5
6
7
8
9
10
11
document.querySelector('#ipt').addEventListener('blur', () => {
setTimeout(() => {
console.log('blur');
}, 100);
});
document.querySelector('#btn').addEventListener('click'() => {
console.log('click');
});
// blur
// click

2. 用mousedown事件代替click事件

  • mousedown事件:当鼠标指针移动到元素上方并按下鼠标按键时,触发mousedown事件。
  • mouseup事件:当在元素上松开鼠标按钮时,会发生mouseup事件。

注意:

mousedown和mouseup与click 事件不同。mousedown事件仅需要按键被按下,而不需要松开即可发生;mouseup事件仅需要松开按钮,当鼠标指针位于元素上方时,放松鼠标按钮就会触发该事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
document.querySelector('#ipt').addEventListener('blur', () => {
console.log('blur');
});
document.querySelector('#btn').addEventListener('click', () => {
console.log('click');
});
document.querySelector('#btn').addEventListener('mousedown', () => {
console.log('mousedown');
});
document.querySelector('#btn').addEventListener('mouseup', () => {
console.log('mouseup');
});
// mousedown
// blur
// mouseup
// click

input文件上传同名文件问题

问题的提出

通常我们在用input做文件上传的时候,会为其绑定change事件,但是这时候会遇到一个问题,当我们在此上传同一个文件的时候,该文件已经缓存到浏览器中了,如果不刷新的话,change事件无法重复触发。

1
2
3
4
5
6
7
8
9
10
11
12
// HTML
<input type="file" id="file" />
// js
document.querySelector('#file').addEventListener('change', () => {
console.log('change');
// ...
})
// 第一次上传 file.xlsx
// change
// 第二次上传 file.xlsx 不会触发change事件

问题的解决

1. 手动触发form的reset方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// HTML
<form id="form">
<input type="file" id="file" />
</form>
// js
document.querySelector('#file').addEventListener('change', () => {
console.log('change');
// ...
document.querySelector('#form').reset();
});
// 第一次上传 file.xlsx
// change
// 第二次上传 file.xlsx
// change

缺点: 不难看出这种方法我们必须为input元素包裹一个form元素,当只包含一个input元素时候这种方法就不适用了。

2. remove掉input元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// HTML
<form id="form">
<input type="file" id="file" />
</form>
// js
let file = document.querySelector('#file');
file.addEventListener('change', () => {
console.log('change');
// ...
file.remove();
document.querySelector('#form').innerHTML = '<input type="file" id="file" />';
});
// 第一次上传 file.xlsx
// change
// 第二次上传 file.xlsx
// change

缺点:这种方法需要修改dom结构了dom结构,可能导致节点树的回流。

3. 更新change事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// HTML
<form id="form">
<input type="file" id="file" />
</form>
// js
let file = document.querySelector('#file');
file.addEventListener('change', () => {
console.log('change');
// ...
file.remove();
file.onchange = function () {
// ...
}
});
// 第一次上传 file.xlsx
// change
// 第二次上传 file.xlsx
// change