请说说focus、blur与focusin、focusout的区别是什么?
在前端开发中,focus
、blur
、focusin
和 focusout
都是与元素焦点相关的事件,但它们之间存在一些关键区别:
1. 事件冒泡:
focus
和blur
事件不冒泡。这意味着当一个元素获得或失去焦点时,只有该元素本身会触发这些事件,其父元素不会收到通知。focusin
和focusout
事件会冒泡。这意味着当一个元素获得或失去焦点时,该元素本身会触发事件,并且事件会沿着 DOM 树向上传播,触发其祖先元素上的相应事件。
2. 事件触发顺序:
当一个元素获得焦点时,事件触发的顺序是:focusin
-> focus
。
当一个元素失去焦点时,事件触发的顺序是:blur
-> focusout
。
3. 使用场景:
-
由于
focus
和blur
不冒泡,它们更适用于处理特定元素的焦点变化,例如:- 表单验证:在
blur
事件中检查输入字段的值是否有效。 - UI 更新:在
focus
事件中高亮输入框,在blur
事件中移除高亮。
- 表单验证:在
-
由于
focusin
和focusout
会冒泡,它们更适用于处理包含多个可聚焦元素的容器的焦点变化,例如:- 跟踪焦点:监听容器的
focusin
和focusout
事件,可以知道焦点是否在容器内,而无需监听每个子元素。 - 动态添加/移除事件监听器:在容器的
focusin
事件中为获得焦点的元素添加事件监听器,在focusout
事件中移除监听器。
- 跟踪焦点:监听容器的
总结:
特性 | focus | blur | focusin | focusout |
---|---|---|---|---|
冒泡 | 否 | 否 | 是 | 是 |
触发时机 | 元素获得焦点 | 元素失去焦点 | 元素获得焦点(冒泡阶段) | 元素失去焦点(冒泡阶段) |
常用场景 | 处理特定元素的焦点变化 | 处理特定元素的焦点变化 | 处理容器的焦点变化 | 处理容器的焦点变化 |
示例:
<div id="container">
<input type="text" id="input1">
<input type="text" id="input2">
</div>
<script>
const container = document.getElementById('container');
const input1 = document.getElementById('input1');
const input2 = document.getElementById('input2');
container.addEventListener('focusin', (event) => {
console.log('Container focusin:', event.target.id);
});
container.addEventListener('focusout', (event) => {
console.log('Container focusout:', event.target.id);
});
input1.addEventListener('focus', () => {
console.log('Input 1 focus');
});
input1.addEventListener('blur', () => {
console.log('Input 1 blur');
});
input2.addEventListener('focus', () => {
console.log('Input 2 focus');
});
input2.addEventListener('blur', () => {
console.log('Input 2 blur');
});
</script>
在这个例子中,当你点击 input1
时,控制台会输出: Container focusin: input1
-> Input 1 focus
。 当你再点击 input2
时,控制台会输出:Input 1 blur
-> Container focusout: input1
-> Container focusin: input2
-> Input 2 focus
. 这清晰地展示了事件的冒泡行为和触发顺序。