- 테이블 자식 요소 추가하기 -
과일 정보와 가격을 보여주는 table 요소를 만들려고 한다.
table 안에 있는 tbody 태그는 id가 fruitTbody 이다.
서버로부터 데이터를 전달 받아 행을 하나씩 추가한다.
서버가 매개변수를 리스트 형태로 전달해 주면,
그 리스트를 가지고 반복문을 돌리면서 tr 태그 안을 하나하나 채운다.
이렇게 완성한 행들을 추가한 뒤에, 각각의 행에 이벤트를 걸어 줘야 한다.
행 하나를 클릭했을 때, 그 과일의 상세 정보를 보여줄 예정이다.
function inputFruitRows(fruitList) {
$.each(fruitList, function(index, item) {
let newRow = ' <tr class="fruitRow" name="' + index + '" row-num="' + index + '">';
newRow += ' <td name="fruit_name">';
newRow += item.name;
newRow += ' </td>';
newRow += ' <td name="fruit_color">';
newRow += item.color;
newRow += ' </td>';
newRow += ' <td name="price">';
newRow += item.price;
newRow += ' </td>';
newRow += ' </tr>';
$('#fruitTbody').append($(newRow));
});
}
- 나중에 생성되는 요소에 이벤트 걸기 -
여기서 문제는 이벤트를 어떻게 거는지다.
결론부터 말하자면,
linkEventRowA() 를 이용하면 이벤트가 걸리지 않고,
linkEventRowB() 를 이용하면 이벤트가 원하던 대로 걸린다.
function linkEventRowA() {
$('tr.fruitRow').on('click', function(e) {
let rowNum = e.currentTarget.attributes['row-num'].value;
showDetail(rowNum);
});
}
function linkEventRowB() {
$('tbody#fruitTbody').on('click', '.rowProductList', function(e) {
let rowNum = e.currentTarget.attributes['row-num'].value;
showDetail(rowNum);
});
}
- 문제점과 해결책 -
linkEventRowA 는 왜 작동하지 않을까?
이유는 tr 태그가 나중에 생성되기 때문이다.
tr.fruitRow 요소를 찾아서 이벤트를 걸어주려고 하는데,
아직 그 tr 요소가 생성되지 않은 상태이다.
결국 대상이 없기 때문에 아무 일도 하지 않고 일을 끝마친다.
반면에 linkEventRowB 는 어떤 원리로 작동할까?
이유는 이벤트를 상위 요소에 위임하기 때문이다.
tbody 태그 안에 tr 태그들이 들어 있다.
tbody 요소는 이미 있고, tr 요소들을 나중에 만들어서 추가한다.
tr이 있든 없든, tbody에게 이벤트를 부탁하면 해결된다.
tbody는 이미 있던 tr이든 나중에 생긴 tr이든 상관하지 않고 이벤트를 적용한다.
document에 이벤트를 위임하기도 한다.
document는 가장 상위 요소이기 때문에 이벤트 위임이 더욱 확실해진다.
$(document).on('click', '.rowProductList', function(e) {
doSomething();
}
어떤 요소에 이벤트를 적용하고 싶을 때,
그 요소 자체에 이벤트를 거는 방식은 direct 또는 directly-bound라고 한다.
이벤트를 걸고 싶은 요소에 직접 걸지 않고,
그 상위 요소에 대신 부탁하는 방식은 delegated 라고 한다.
다음 페이지 참고
https://api.jquery.com/on/
Direct and delegated event handlers
The majority of browser events bubble, or propagate, from the deepest, innermost element (the event target) in the document where they occur all the way up to the body and the document element. In Internet Explorer 8 and lower, a few events such as change and submit do not natively bubble but jQuery patches these to bubble and create consistent cross-browser behavior.
If selector is omitted or is null, the event handler is referred to as direct or directly-bound. The handler is called every time an event occurs on the selected elements, whether it occurs directly on the element or bubbles from a descendant (inner) element.
When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
Event handlers are bound only to the currently selected elements; they must exist at the time your code makes the call to .on(). To ensure the elements are present and can be selected, place scripts after the elements in the HTML markup or perform event binding inside a document ready handler. Alternatively, use delegated event handlers to attach event handlers.
Delegated event handlers have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated event handlers to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
In addition to their ability to handle events on descendant elements not yet created, another advantage of delegated event handlers is their potential for much lower overhead when many elements must be monitored. On a data table with 1,000 rows in its tbody, this example attaches a handler to 1,000 elements:
$( "#dataTable tbody tr" ).on( "click", function() {
console.log( $( this ).text() );
});
An event-delegation approach attaches an event handler to only one element, the tbody, and the event only needs to bubble up one level (from the clicked tr to tbody):
$( "#dataTable tbody" ).on( "click", "tr", function() {
console.log( $( this ).text() );
});
Note: Delegated event handlers do not work for SVG.
220331
'JavaScript' 카테고리의 다른 글
select 태그에서 option 선택 값 바뀔 때마다 이벤트 걸기 (on change) (0) | 2022.04.02 |
---|---|
JavaScript 이벤트 객체란? 구조와 내용, 속성 값 꺼내 오기 (0) | 2022.04.02 |
여러 계층에 걸쳐서 자식 요소를 선택하는 방법 jQuery 선택자 (0) | 2022.04.02 |
[JavaScript] var / let / const 차이점 비교 (스코프, 호이스팅, 선언) (0) | 2022.03.19 |
자바스크립트가 싱글 스레드이면서 비동기인 원리 (ft. event loop) (0) | 2022.03.17 |