์ด ๊ธ๋ก ์ป์ ์ ์๋ ์ ๋ณด
1. Event์ CustomEvent ( + dispatchEvent )
2. ํฉ์ฑ ์ด๋ฒคํธ์ ๊ฐ๋
3. ์ด๋ฒคํธ ๋ฐ์ ๋ฐฉ์ ๋ฐ ์์
4. input,label์์ click event๊ฐ ๋ ๋ฒ ์คํ๋๋ ์ด์์ ํด๊ฒฐ ๋ฐฉ๋ฒ
0. ๊ฐ์
์ ๋ฌด(Next.js 14, storybook ์ฌ์ฉ ์ค) ์ฝ๋ ๋ฆฌ๋ทฐ ์ค ๋ค์ ์์์ ๊ฐ์ด input๊ณผ label์ ์ฐ๊ฒฐ ํ, onClick ์ด๋ฒคํธ๋ฅผ ๋ฃ์ div๋ก ๊ฐ์ธ๋ ๋งํฌ์ ์ ๊ตฌ์ฑํ๊ฒ ๋๋ฉด label ์์ญ์ ๋๋ ์ ๋ click event๊ฐ ๋ ๋ฒ์คํ๋๋ ์ด์๊ฐ ๋ฐ์ํ์ฌ ํด๋น ์ด์์ ๋ํด ์์๋ณด๋ ค๊ณ ํฉ๋๋ค.
See the Pen Untitled by ์ค์ฐฝํ (@ibgcsnij-the-selector) on CodePen.
1. ๋ฌธ์ ์ ๊ทผ ๋ฐฉ๋ฒ
1-1. bubbling๊ณผ capturing ์ฐ์
ํด๋น ์ด์๋ฅผ ์ ํ๊ณ ์ ์ผ ๋จผ์ bubbling๊ณผ capturing ์ ๋ ์ฌ๋ ธ์ง๋ง stgopPropagation ๋ฉ์๋๋ง์ผ๋ก ํด๊ฒฐ๋์ง ์์๊ณ ์ผ๋ฐ์ ์ธ ๋ฒ๋ธ๋ง์ ๊ตฌ์กฐ์์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ชจ ์์ ๋ด ์ค์ฒฉ๋ ์์์์๊ฐ 2๊ฐ ์ด์์ด ์๋๋ผ๋ ๋ถ๋ชจ ์์๊ฐ 2๋ฒ ์คํ๋๋ ํ์์ด ๋ฐ์ํ์ง ์์์ต๋๋ค.
See the Pen Untitled by ์ค์ฐฝํ (@ibgcsnij-the-selector) on CodePen.
๊ทธ๋์ ๊ด๋ จ๋ ์ฝ๋ ์์ ๋ค๋ฅธ ์ด์๋ค(useRef, aria-labelledby, storybook)์ ์ฐพ์๋ณด์์ผ๋, click event์ ์ฐ๊ด๋ ๋ด์ฉ์ ์ฐพ์๋ณผ ์ ์์์ต๋๋ค.
๋ฒ๋ธ๋ง๊ณผ ์บก์ฒ๋ง ๊ด๋ จ ๋ฌธ์
1-2. preventDefault๋ก click event๊ฐ ๋ ๋ฒ ์คํ๋๋ ์ด์๋ฅผ ํด๊ฒฐํ์์ผ๋...
๋ค๋ฅธ ํ์์ ๋์์ผ๋ก preventDefault๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ์ด์๋ฅผ ํด๊ฒฐํ ์ ์์์ ํ์ธํ์์ผ๋, ์ ํํ ์์ธ ํ์ธ์ด ์ด๋ ค์ stack overflow์ ๊ด๋ จ๋ ์์ธ์ ์ฐพ๊ธฐ ์์ํ์์ต๋๋ค.
1-3. stack overflow์์ ๊ด๋ จ๋ ์์ธ ๋ฐ๊ฒฌ
stack overflow์์ ์๋์ ๊ฐ์ ๋ต๋ณ์ ์ฐพ๊ฒ ๋์์ต๋๋ค.
This happens because of what the HTML spec describes at 4.10.4:
For example, on platforms where clicking a checkbox label checks the checkbox, clicking the label in the following snippet could trigger the user agent to run synthetic click activation steps on the input element, as if the element itself had been triggered by the user:
<label><input type=checkbox name=lost> Lost</label>
On other platforms, the behavior might be just to focus the control, or do nothing.
This means that when a <label> is clicked, the browser creates a second "synthetic" click event on the associated <input> element, in order to toggle its state.
The reason divClicked is triggered twice, is because the first event which comes from the <label> bubbles up to the <div>, and also the second, synthetic click event bubbles up to the <div>.
์ ๋ด์ฉ์ ๊ฐ๋ตํ๊ฒ ํด์ํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์์ ์ฝ๋์์ checkbox๋ฅผ ๊ฐ์ธ๊ณ ์๋ label์ ํด๋ฆญํ๋ฉด ํฉ์ฑ ํด๋ฆญ ์ด๋ฒคํธ(ํฉ์ฑ ํด๋ฆญ ํ์ฑํ ๋จ๊ณ)๋ฅผ ์คํํ๋๋ก ๋์ด ์๋ค
- ๋ธ๋ผ์ฐ์ ๊ฐ ์ํ๋ฅผ ์ ํํ๊ธฐ ์ํด label์ ํด๋ฆญํ๋ฉด ์ฐ๊ฒฐ๋ checkbox input ์์์ ๋ ๋ฒ์งธ ํฉ์ฑ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ์์ฑํ๋ค๋ ์๋ฏธ(๊ธฐ์กด checkbox input์ ์ด๋ฒคํธ๋ label๊ณผ ์ฐ๊ฒฐ๋จ)
- ๊ฒฐ๊ตญ div์ click event๊ฐ ๋ ๋ฒ ์คํ๋๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค
- label์์ ๋ฐ์ํ๋ ์ฒซ ๋ฒ์งธ ์ด๋ฒคํธ๊ฐ div๊น์ง bubbling ๋์ด div click event ์ฒซ ๋ฒ์งธ ์คํ
- checkbox input ์์์ ์์ฑ๋ ๋ ๋ฒ์งธ ์ด๋ฒคํธ๊ฐ div๊น์ง bubbling ๋์ด div click event ๋ ๋ฒ์งธ ์คํ
์ ๋ ์ฒ์ ๋ต๋ณ์ ๋ดค์ ๋ ํฉ์ฑ ์ด๋ฒคํธ์ event ๋ฐ์ ๋ฐฉ์์ ๊ดํ ๊ฐ๋ ์ ๋ชฐ๋ผ, ํ ๋ฒ์ ์ดํดํ๊ธฐ ์ด๋ ค์ ์ต๋๋ค.
๊ทธ๋์ ํฉ์ฑ ์ด๋ฒคํธ์ ๊ฐ๋ ๊ณผ ๋ต๋ณ์๊ฐ ์ฒจ๋ถํ ๊ด๋ จ๋ฌธ์๋ฅผ ํตํด event ๋ฐ์ ๋ฐฉ์๊ณผ ๊ด๋ จ๋ ํค์๋๋ฅผ ์์๋ณด์์ต๋๋ค.
2. ํฉ์ฑ ์ด๋ฒคํธ์ ์ปค์คํ ์ด๋ฒคํธ
mdn์์ Event ๋ํด ์ฐพ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ค๋ช ์ด ๋์ต๋๋ค.
The Event() constructor creates a new Event object. An event created in this way is called a synthetic event, as opposed to an event fired by the browser, and can be dispatched by a script.
์ฆ, new Event๋ก ์ด๋ฒคํธ๋ฅผ ์์ฑํ๋ฉด ๋ธ๋ผ์ฐ์ ์ ์ํด ๋ฐ์๋ ์ด๋ฒคํธ์ ๋ฌ๋ฆฌ ํฉ์ฑ ์ด๋ฒคํธ ๋ผ๊ณ ํ๋ฉฐ, ์คํฌ๋ฆฝํธ์ ์ ๋ฌ๋๋ค๊ณ ํฉ๋๋ค.
์ฌ๊ธฐ์ ํฉ์ฑ ์ด๋ฒคํธ ํค์๋๊ฐ ๋์ค๋๋ฐ, ์คํฌ๋ฆฝํธ์ ์ํด ์ ๋ฌ ๋๋ค๋ ์๋ฏธ๊ฐ ํ ๋ฒ์ ์ดํด๋์ง์์ต๋๋ค.
๊ด๋ จ๋ ๋ด์ฉ์ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฌ์ดํธ์ ์ปค์คํ ์ด๋ฒคํธ๋ฅผ ๋ณด๋ฉด ์ดํดํ ์ ์๋๋ฐ, ํด๋น ๋งํฌ์์ click event๊ฐ ๋ ๋ฒ ์คํ๋๋ ์ด์์ ๊ด๋ จ๋ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
( ํด๋น ๊ธ์ bubbles(bubbling), cancelable(preventDefault), isTrusted ๋ฑ ์ข์ ๋ด์ฉ๋ค์ด ๋ง์ผ๋ ๊ผญ ์ฝ์ด๋ณด์๋ ๊ฑธ ์ถ์ฒ๋๋ฆฝ๋๋ค. )
2-1. Event,CustomEvent์ dispatchEvent
- new Event์ new CustomEvent๋ฅผ ํตํด script์์ ๋ธ๋ผ์ฐ์ ์ด๋ฒคํธ(ex. button element์ click ์ด๋ฒคํธ)์ ๋ค๋ฅธ ์ปค์คํ
์ด๋ฒคํธ๋ฅผ ์์ฑํ ์ ์๋ค
- Event๋ ๋ด์ฅ ์ด๋ฒคํธ, ์ปค์คํ ์ด๋ฒคํธ ๋ ๋ค ์ฌ ์ ์์
- CustomEvent๋ Event์ ๋ฌ๋ฆฌ ์ด๋ฒคํธ ๊ด๋ จ ์ ๋ณด๋ฅผ ๋ช ์ํด ์ค ์ ์์ (๋ค๋ฅธ ์ด๋ฒคํธ์ ์ถฉ๋ ํํผ)
- isTrusted : ์คํฌ๋ฆฝํธ๋ฅผ ํตํด ์์ฑ๋๋ ์ด๋ฒคํธ๋ false, ์ฌ์ฉ์ ์ก์ (๋ธ๋ผ์ฐ์ ์ด๋ฒคํธ)๋ฅผ ํตํด ๋ง๋ ์ด๋ฒคํธ๋ true
- ์์ฑํ ์ด๋ฒคํธ๋ dispatchEvent ๋ฉ์๋๋ฅผ ํตํด ์ด๋ฒคํธ๋ฅผ ์คํ์ํค๋ฉด ์ผ๋ฐ ๋ธ๋ผ์ฐ์ ์ด๋ฒคํธ์ฒ๋ผ addEventListner๋ก ๊ฐ์งํ ์ ์๋ค
- ์ด๋ฒคํธ ์์ฑ ์ cancelable: true๋ก ์ค์ ํ ๊ฒฝ์ฐ preventDefault ๋ฉ์๋๋ฅผ ์คํํ๋ฉด dispatchEvent์ return ๊ฐ์ด false๊ฐ ๋๋ค (์ด ๋ฐฉ์ ๋๋ฌธ์ preventDefault๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ์กด ์ด๋ฒคํธ๋ฅผ ์ทจ์ํ ์ ์์๋ ๊ฒ)
See the Pen Event, CustomEvent by ์ค์ฐฝํ (@ibgcsnij-the-selector) on CodePen.
3. ์ด๋ฒคํธ ๋ฐ์ ๋ฐฉ์
https://html.spec.whatwg.org/multipage/webappapis.html#fire-a-click-event
์ ๋ฌธ์์์ ๋ณผ ์ ์๋ ์ด๋ฒคํธ ๋ฐ์ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด๋ฒคํธ ์ด๋ฆ์ test_event๋ผ๊ณ ๊ฐ์ ํ๋ฉฐ, ์ ๋ฌธ์์์ ๋งํ๋ ์ด๋ฒคํธ ๋ฐ์ ๋ฐฉ์์ ๊ธฐ๋ณธ ๋ธ๋ผ์ฐ์ ์ด๋ฒคํธ๋ฅผ ๋งํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
- PointerEvent๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฒคํธ๋ฅผ ์์ฑํฉ๋๋ค.
- ์ด๋ฒคํธ type์ test_event๋ก ์ด๊ธฐํํฉ๋๋ค.
- bubbles์ cancelable ์์ฑ์ true๋ก ์ด๊ธฐํํฉ๋๋ค. (default ๊ฐ)
- composed ์์ฑ ๊ฐ์ ์ค์ ํฉ๋๋ค.
- composed : ์ด๋ฒคํธ๊ฐ ํด๋น ๋์์ ๋ฃจํธ์ธ ShadowRoot ๋ ธ๋๋ฅผ ์ง๋ ๋ฆฌ์ค๋๋ฅผ ํธ์ถํ๋ฉด true์ด๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด false
- isTrusted ์์ฑ ๊ฐ ์ค์
- ํค ์ ๋ ฅ ์ฅ์น์ ํ์ฌ ์ํ์ ๋ฐ๋ผ ์ด๋ฒคํธ์ ctrlKey, ShiftKey, altKey ๋ฐ MetaKey ์์ฑ์ด ์๋ ๊ฒฝ์ฐ ์ด๊ธฐํํฉ๋๋ค. (์ฌ์ฉํ ์ ์๋ ํค์ ๊ฒฝ์ฐ false)
- view ์์ฑ ๊ฐ์ window ๊ฐ์ฒด๋ก ์ด๊ธฐํ ํฉ๋๋ค. (์๋ ๊ฒฝ์ฐ null)
- ์ด๋ฒคํธ์ getModifierState() ๋ฉ์๋๋ ํค ์
๋ ฅ ์ฅ์น์ ํ์ฌ ์ํ๋ฅผ ์ ์ ํ๊ฒ ์ค๋ช
ํ๋ ๊ฐ์ ๋ฐํํ๋ ๊ฒ ์
๋๋ค.
- getModifierState() : ์ง์ ๋ ์์ ์ ํค์ ํ์ฌ ์ํ๋ฅผ ๋ฐํํฉ๋๋ค. ์์ ์๊ฐ ํ์ฑ ์ํ์ด๋ฉด(์ฆ, ์์ ์ ํค๊ฐ ๋๋ฆฌ๊ฑฐ๋ ์ ๊ธด ๊ฒฝ์ฐ) true์ด๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด false
- ์ด๋ฒคํธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค. (dispatchEvent)
์ด๋ฒคํธ ๋ฐ์ ๋ฐฉ์์์ ์ฐ๋ฆฌ๊ฐ ์์๋ดค๋ ์ด๋ฒคํธ์ ๋ค์ํ ๊ฐ๋ ์ด ๋์จ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
( ์ฌ๊ธฐ์ composed ์์ฑ์์ Shadow Dom์ Shadow Root์ ๋ํ ๊ฐ๋ ์ด ๋์ค๋๋ฐ, ์ฌ๊ธฐ์ ์ค๋ช ํ๊ธฐ์ ๋๋ฌด ๊ธธ์ด์ง๋ ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ๋ ๊ฒ์ ์ถ์ฒ๋๋ฆฝ๋๋ค.)
Shadow Dom ๊ด๋ จ ๋งํฌ
- ์น ์ปดํฌ๋ํธ - MDN
- Shadow Dom ์ฌ์ฉํ๊ธฐ - MDN
- Shadow Dom ์ฌ์ฉ ์ฌ๋ก - Shadow DOM์ผ๋ก ์ ๊ท ํ๋ก์ ํธ์ ์คํ์ผ์ ์งํค๋ ๋ฐฉ๋ฒ(์ธํ๋ฐ)
4. ์์ธ ๋ถ์
์ด์ ์์๋ณธ ๊ฐ๋ ์ผ๋ก 1-3์์ ๋ฐ๊ฒฌํ ์์ธ์ ๋ค์ ๋ถ์ํด๋ณด๊ฒ ์ต๋๋ค.
- ์์ ์ฝ๋์์ checkbox๋ฅผ ๊ฐ์ธ๊ณ ์๋ label์ ํด๋ฆญํ๋ฉด ํฉ์ฑ ํด๋ฆญ ์ด๋ฒคํธ(ํฉ์ฑ ํด๋ฆญ ํ์ฑํ ๋จ๊ณ)๋ฅผ ์คํํ๋๋ก ๋์ด ์๋ค
- ๋ธ๋ผ์ฐ์ ๊ฐ ์ํ๋ฅผ ์ ํํ๊ธฐ ์ํด label์ ํด๋ฆญํ๋ฉด ์ฐ๊ฒฐ๋ checkbox input ์์์ ๋ ๋ฒ์งธ ํฉ์ฑ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ์์ฑํ๋ค๋ ์๋ฏธ(๊ธฐ์กด checkbox input์ ์ด๋ฒคํธ๋ label๊ณผ ์ฐ๊ฒฐ๋จ)
- ๊ฒฐ๊ตญ div์ click event๊ฐ ๋ ๋ฒ ์คํ๋๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค
- label์์ ๋ฐ์ํ๋ ์ฒซ ๋ฒ์งธ ์ด๋ฒคํธ๊ฐ div๊น์ง bubbling ๋์ด div click event ์ฒซ ๋ฒ์งธ ์คํ
- checkbox input ์์์ ์์ฑ๋ ๋ ๋ฒ์งธ ์ด๋ฒคํธ๊ฐ div๊น์ง bubbling ๋์ด div click event ๋ ๋ฒ์งธ ์คํ
๐ก ๋ถ์
1. checkbox๋ฅผ ๊ฐ์ธ๊ณ ์๋ label์ ํด๋ฆญํ๋ฉด new Event๋ก checkbox์ ์ฐ๊ฒฐ๋ ์ด๋ฒคํธ๋ฅผ ์คํ์ํค๋ ํฉ์ฑ ํด๋ฆญ ์ด๋ฒคํธ ์์ฑ (2.ํฉ์ฑ ์ด๋ฒคํธ์ ์ปค์คํ ์ด๋ฒคํธ)
2. new Event๋ก ์์ฑํ ์ด๋ฒคํธ๋ bubbles default ๊ฐ์ด ture์ด๊ธฐ ๋๋ฌธ์ bubbling๋์ด div event ์คํ
3. ๊ธฐ์กด checkbox์ ์ด๋ฒคํธ ์คํ์ผ๋ก bubbling๋์ด div event ๋ ๋ฒ ์คํํ๊ฒ ๋จ
์์๋ฅผ ์ ๋ฆฌํด๋ณด์๋ฉด, ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ํฉ์ฑ ํด๋ฆญ event ์์ฑ
- ํฉ์ฑ ํด๋ฆญ event ์คํ
- div event bubbling
- checkbox event ์คํ
- div event bubbling
๋๋ฌธ์ 0. ๊ฐ์์ ์ฝ๋์์ ๋ ธ์ถ๋๋ alert ์์๊ฐ div -> input -> div ์ธ ๊ฒ์ ๋๋ค. (์๋กญ๊ฒ ์์ฑ๋ ํฉ์ฑ ํด๋ฆญ event์๋ alert์ด ์์ผ๋ฏ๋ก bubbling ๋ div๊ฐ ๋จผ์ ๋ ธ์ถ๋๋ ๊ฒ)
์ ์์๋ฅผ ์ด์ฉํ๊ฒ ๋๋ฉด div event๊ฐ ๋ ๋ฒ ์คํ๋๋ ํ์์ ๋ํด ๋ ๊ฐ์ง ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋์ถํ ์ ์์ต๋๋ค.(๋ค์ ์์ ์ฝ๋ ์ฐธ๊ณ )
1. div event์ preventDefault ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ 3๋ฒ ๊ณผ์ ์์ ๊ธฐ์กด checkbox event๋ฅผ dispatchEvent๋ก ์คํํ ๋ false๊ฐ ๋์ด checkbox event๊ฐ ์ค๋จ๋์ด ์ค๋ณต ์คํ ๋ฐฉ์ง -> 4,5๋ฒ ๊ณผ์ ์ด ์๋ต๋์ด ์์ ์ฝ๋์์๋ div alert๋ง ๋ ธ์ถ๋จ
2. ๊ธฐ์กด checkbox event์ stopPropagation ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ์กด checkbox event์์ bubbling์ ๋ง์ ์ค๋ณต ์คํ ๋ฐฉ์ง -> 5๋ฒ ๊ณผ์ ์ด ์๋ต๋์ด div alert -> checkbox alert ์์ผ๋ก ๋ ธ์ถ๋จ
See the Pen input,label issue solution1 by ์ค์ฐฝํ (@ibgcsnij-the-selector) on CodePen.
See the Pen input,label issue solution2 by ์ค์ฐฝํ (@ibgcsnij-the-selector) on CodePen.
๋ง์น๋ฉฐ
๊ทธ๋ฅ ์ง๋์น ์๋ ์์๋ ๋ฌธ์ ์์ง๋ง, ํ๋ ํ๋ ๋ถ์ํด๋ณด๋ฉฐ ์ด๋ฒคํธ์ ๊ด๋ จ๋ ๋ค์ํ ๊ฐ๋ ๊ณผ ์๋ ์๋ฆฌ ๋ฑ์ ํ์ ํ ์ ์์ด์ ๋ป ๊น์ ์๊ฐ์ด์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ต๋ํ ์๊ธฐ ์ฝ๊ฒ ์์ฑํ๋ ค๊ณ ๋ ธ๋ ฅํ์๋๋ฐ, ์ดํด๊ฐ ์๋๋ ๋ถ๋ถ์ด ์์ผ์๊ฑฐ๋ ํ๋ฆฐ ๋ถ๋ถ์ด ์๋ค๋ฉด ์ ๊ทน์ ์ธ ํผ๋๋ฐฑ ๋ถํ๋๋ฆฌ๊ฒ ์ต๋๋ค.
๊ธด ๊ธ ๋ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๐
'Front-End > HTML,CSS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
style lint selector-max-type: 0์ ์ด๋ป๊ฒ ์๋ํ ๊น? (0) | 2024.10.27 |
---|
๋๊ธ