728x90
반응형
SMALL

이벤트 캡처링, 버블링 그리고 disabled vs readonly
이벤트 흐름 3단계
DOM에서 이벤트가 발생하면 3단계를 거친다.
[1. 캡처링] window → document → div → button (위에서 아래로)
↓
[2. 타겟] button (실제 클릭한 요소)
↓
[3. 버블링] button → div → document → window (아래에서 위로)
기본 동작: 버블링 단계에서 실행
// 기본 (버블링 단계에서 실행)
div.addEventListener('click', handler);
// 캡처링 단계에서 실행하려면 명시적으로 설정
div.addEventListener('click', handler, true);
캡처링 vs 버블링 실행 순서
<div id="parent">
<button id="child">클릭</button>
</div>
parent.addEventListener('click', () => console.log('부모-캡처링'), true);
parent.addEventListener('click', () => console.log('부모-버블링'));
child.addEventListener('click', () => console.log('자식'));
button 클릭 시 출력 순서:
1. "부모-캡처링" (캡처링 단계)
2. "자식" (타겟 단계)
3. "부모-버블링" (버블링 단계)
stopPropagation()으로 전파 막기
캡처링에서 막으면
parent.addEventListener('click', (e) => {
e.stopPropagation();
console.log('부모');
}, true);
child.addEventListener('click', () => console.log('자식'));
[캡처링] parent → 실행 + 전파 중단
❌ child까지 안 내려감
결과: "부모"만 출력
버블링에서 막으면
parent.addEventListener('click', () => console.log('부모'));
child.addEventListener('click', (e) => {
e.stopPropagation();
console.log('자식');
});
[캡처링] parent → child (실행 없이 내려감)
[타겟] child → 실행 + 전파 중단
[버블링] ❌ parent까지 안 올라감
결과: "자식"만 출력
disabled는 다르다
stopPropagation()은 이벤트를 막는 것이고, disabled는 이벤트 자체가 발생하지 않는다.
<div onClick={handleClick}>
<input disabled />
</div>
input(disabled) 클릭
↓
"이 요소는 disabled네? 이벤트 없음"
↓
끝. 캡처링도 버블링도 없음
부모에 이벤트가 있든, 캡처링으로 설정했든 상관없이 아무 일도 안 일어난다.
disabled vs readonly
| 속성 | 입력 가능 | 이벤트 발생 | 버블링 |
| readonly | ❌ | ✅ | ✅ |
| disabled | ❌ | ❌ | ❌ |
readonly일 때
input(readonly) 클릭
↓
[캡처링] div → input
↓
[타겟] input → 이벤트 발생!
↓
[버블링] input → div → onClick 실행!
disabled일 때
input(disabled) 클릭
↓
이벤트 없음. 끝.
비유로 정리
disabled → 공을 아예 안 던짐
readonly → 공을 던짐, 정상 진행
stopPropagation() → 공을 던졌는데 중간에 막음
결론
- 이벤트는 캡처링 → 타겟 → 버블링 순서로 흐른다
- 기본 이벤트 리스너는 버블링 단계에서 실행된다
- stopPropagation()은 이벤트 전파를 막는다
- disabled는 이벤트 자체가 발생하지 않는다
- 부모에 이벤트 위임하고 자식 입력만 막으려면 → readonly 사용
728x90
반응형
LIST
'javascript' 카테고리의 다른 글
| JavaScript 클래스: 생성자 함수 vs 클래스(static,public,private) 문법 (0) | 2026.01.24 |
|---|---|
| JavaScript 원시값의 비밀: undefined와 null은 메모리를 차지할까? (0) | 2026.01.23 |
| 브라우저 vs Node.js: JavaScript 실행 환경의 차이 (1) | 2026.01.21 |
| JavaScript 실행 방식: 컴파일러 vs 인터프리터 vs JIT (0) | 2026.01.21 |
| 실행 컨텍스트 (Execution Context) 완벽 가이드 (0) | 2026.01.21 |
댓글