동적으로 생성 된 요소에 대한 이벤트 바인딩?


1677

페이지의 모든 선택 상자를 반복 .hover하고 너비를 사용하여 약간의 돌리기를하기 위해 이벤트를 바인딩하는 코드 가 있습니다 mouse on/off.

이것은 페이지 준비시 발생하며 정상적으로 작동합니다.

내가 가진 문제는 초기 루프 후 Ajax 또는 DOM을 통해 추가 한 선택 상자에 이벤트가 바인딩되지 않는다는 것입니다.

이 플러그인 ( jQuery Live Query Plugin ) 을 찾았 지만 플러그인을 사용하여 페이지에 다른 5k를 추가하기 전에 누군가 jQuery를 사용하거나 다른 옵션으로이를 수행하는 방법을 알고 싶습니다.

답변:


2249

jQuery 1.7부터 다음을 사용해야합니다 jQuery.fn.on.

$(staticAncestors).on(eventName, dynamicChild, function() {});

이 전에 권장되는 접근 방식은 다음을 사용하는 것입니다 live().

$(selector).live( eventName, function(){} );

그러나 live()1.7에서는 더 이상 사용되지 않으며 on()1.9에서는 완전히 제거되었습니다. live()서명 :

$(selector).live( eventName, function(){} );

... 다음 on()서명 으로 대체 할 수 있습니다 .

$(document).on( eventName, selector, function(){} );

예를 들어, 페이지에서 클래스 이름으로 요소를 동적으로 생성 하는 경우 이미 존재하는 상위 항목에dosomething 이벤트를 바인딩 합니다 (여기서는 문제의 핵심이므로 바인딩 할 내용이 필요합니다. 동적 콘텐츠)의 경우 가장 쉬운 옵션은 document입니다. 염두에 두는 document것이 가장 효율적인 방법은 아닙니다 .

$(document).on('mouseover mouseout', '.dosomething', function(){
    // what you want to happen when mouseover and mouseout 
    // occurs on elements that match '.dosomething'
});

이벤트가 바인드 될 때 존재하는 모든 상위는 괜찮습니다. 예를 들어

$('.buttons').on('click', 'button', function(){
    // do something here
});

에 적용

<div class="buttons">
    <!-- <button>s that are generated dynamically and added here -->
</div>

7
live 메소드는 특정 이벤트에 대해서만 작동하며 loadedmetadata와 같은 다른 이벤트에는 작동하지 않습니다. (문서의 경고 부분을 참조하십시오.)
Sam Dutton

48
이벤트 위임에 대한 자세한 내용은 learn.jquery.com/events/event-delegation에서 확인하십시오 .
Felix Kling

9
순수한 자바 스크립트 / 바닐라 js로 이것을 달성 할 수있는 방법이 있습니까?
Ram Patra

15
@Ramswaroop jQuery로 할 수있는 모든 작업은 jQuery없이 수행 할 수 있습니다. 다음은 jQuery가없는 이벤트 위임의 좋은 예입니다.
Dave

5
@ dave 왜 당신이 지적한 답변이 여기에 나열되어 있지 않은지 궁금합니다. Eli는 가능하면 플러그인이없는 솔루션을 분명히 요청했습니다.
Ram Patra

377

의 설명서에 좋은 설명이 jQuery.fn.on있습니다.

한마디로 :

이벤트 핸들러는 현재 선택된 요소에만 바인딩됩니다. 코드가 호출 할 때 페이지에 존재해야합니다 .on().

따라서 다음 예제 #dataTable tbody tr에서는 코드가 생성되기 전에 존재해야합니다.

$("#dataTable tbody tr").on("click", function(event){
    console.log($(this).text());
});

새 HTML이 페이지에 삽입되는 경우 다음에 설명 된대로 위임 된 이벤트를 사용하여 이벤트 핸들러를 첨부하는 것이 좋습니다.

위임 된 이벤트 는 나중에 문서에 추가 된 하위 요소의 이벤트를 처리 할 수 ​​있다는 이점이 있습니다. 예를 들어, 테이블이 존재하지만 코드를 사용하여 행이 동적으로 추가되면 다음이 처리합니다.

$("#dataTable tbody").on("click", "tr", function(event){
    console.log($(this).text());
});

아직 생성되지 않은 하위 요소의 이벤트를 처리하는 기능 외에도 위임 된 이벤트의 또 다른 장점은 많은 요소를 모니터링해야 할 때 오버 헤드가 훨씬 낮아질 수 있다는 것입니다. 에 1,000 개의 행이있는 데이터 테이블 tbody에서 첫 번째 코드 예제는 1,000 개의 요소에 핸들러를 연결합니다.

위임 된 이벤트 접근 방식 (두 번째 코드 예)은 이벤트 핸들러를 하나의 요소 ()에만 연결하며 이벤트 tbody는 클릭에서에서로 한 수준 만 버블 링하면 tr됩니다 tbody.

참고 : 위임 된 이벤트는 SVG에서 작동하지 않습니다 .


11
이 방법은 문서에서 검색하는 것이 아니라 특정 테이블에서 위임하는 것이 더 빠르기 때문에 더 나은 대답이 될 것입니다 (검색 영역이 훨씬 작음)
msanjay

5
@msanjay : 검색을 요소에 더 가깝게 타겟팅하는 것이 바람직하지만 검색 / 속도 차이는 실제로 매우 미미합니다. 당신은 아무것도 알아 차리려면 초당 50,000 번을 클릭해야 할 것입니다 :)
사라짐 코딩

2
이 방법을 tr과 같은 적절한 선택기 로 변경 하여 행의 체크 박스 클릭 처리에 적용 할 수 있습니까 'input[type=checkbox]'? 그러면 새로 삽입 된 행에 대해 자동으로 처리됩니까?
JoeBrockhaus

1
감사합니다! 이것은 내 문제를 해결합니다. 이 간단한 문장은 "이벤트 핸들러는 현재 선택된 요소에만 바인드되어 있으며 코드를 호출 할 때 페이지에 존재해야합니다 ..."
Dennis Fazekas

216

이것은 라이브러리 나 플러그인이없는 순수한 JavaScript 솔루션입니다.

document.addEventListener('click', function (e) {
    if (hasClass(e.target, 'bu')) {
        // .bu clicked
        // Do your thing
    } else if (hasClass(e.target, 'test')) {
        // .test clicked
        // Do your other thing
    }
}, false);

hasClass이다

function hasClass(elem, className) {
    return elem.className.split(' ').indexOf(className) > -1;
}

Live demo

신용은 Dave와 Sime Vidas에게갑니다

보다 현대적인 JS를 사용하여 hasClass다음과 같이 구현할 수 있습니다.

function hasClass(elem, className) {
    return elem.classList.contains(className);
}


6
분할하는 대신 Element.classList 를 사용할 수 있습니다
Eugen Konkov

2
@EugenKonkov Element.classList는 이전 브라우저에서 지원되지 않습니다. 예를 들어 IE <9입니다.
Ram Patra

2
jQuery 대신 바닐라 스크립트를 사용하여 작업을 수행하는 방법에 대한 좋은 기사 -toddmotto.com/…
Ram Patra

2
버블 링은 어떻습니까? 관심있는 요소의 하위 요소에서 클릭 이벤트가 발생하면 어떻게됩니까?
Andreas Trantidis

73

객체를 만들 때 객체에 이벤트를 추가 할 수 있습니다. 다른 시간에 여러 객체에 동일한 이벤트를 추가하는 경우 명명 된 함수를 만드는 것이 좋습니다.

var mouseOverHandler = function() {
    // Do stuff
};
var mouseOutHandler = function () {
    // Do stuff
};

$(function() {
    // On the document load, apply to existing elements
    $('select').hover(mouseOverHandler, mouseOutHandler);
});

// This next part would be in the callback from your Ajax call
$("<select></select>")
    .append( /* Your <option>s */ )
    .hover(mouseOverHandler, mouseOutHandler)
    .appendTo( /* Wherever you need the select box */ )
;

49

이벤트 바인딩 호출을 함수로 래핑 한 다음 문서에서 한 번 준비하고 새 DOM 요소를 추가하는 이벤트 후에 한 번만 두 번 호출 할 수 있습니다. 그렇게하면 기존 요소에 동일한 이벤트를 두 번 바인딩하지 않으려면 기존 이벤트를 바인드 해제하거나 새로 작성된 DOM 요소에만 바인딩해야합니다. 코드는 다음과 같습니다.

function addCallbacks(eles){
    eles.hover(function(){alert("gotcha!")});
}

$(document).ready(function(){
    addCallbacks($(".myEles"))
});

// ... add elements ...
addCallbacks($(".myNewElements"))

2
이 게시물은 내가 같은 양식을로드하고 1,2,4,8,16 ... 제출을 얻는 데 문제가 있음을 이해하는 데 실제로 도움이되었습니다. .live ()를 사용하는 대신 내 .load () 콜백에서 .bind ()를 사용했습니다. 문제 해결됨. 감사!
토마스 맥 카베

42

; .live()대신에 사용하십시오 .bind(). 는 Ajax 요청이 실행 된 후 체크 박스에 .live()바인딩 .hover됩니다.


32
이 방법 live()은 버전 1.7에서 사용되지 않으며 on버전 1.9에서 삭제되었습니다.
chridam

27

동적으로 생성 된 요소에 대한 이벤트 바인딩

단일 요소 :

$(document.body).on('click','.element', function(e) {  });

자식 요소 :

 $(document.body).on('click','.element *', function(e) {  });

추가됨을 확인하십시오 *. 해당 요소의 모든 자식에 대해 이벤트가 트리거됩니다.

나는 그것을 알아 차렸다 :

$(document.body).on('click','.#element_id > element', function(e) {  });

더 이상 작동하지 않지만 이전에는 작동했습니다. Google CDN 에서 jQuery를 사용 하고 있지만 변경했는지는 알 수 없습니다.


그러나 그들은 (document.body) 조상은 거의 모든 것이 될 수 있다고 말하지 않습니다
MadeInDreams

25

live () 메소드를 사용하여 onclick 이벤트와 같은 요소 (새로 작성된 요소)를 이벤트 및 핸들러에 바인딩 할 수 있습니다.

다음은 내가 작성한 샘플 코드입니다. live () 메서드가 선택한 요소 (새로 만든 요소)를 이벤트에 바인딩하는 방법을 확인할 수 있습니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
    </head>

    <body>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js"></script>

        <input type="button" id="theButton" value="Click" />
        <script type="text/javascript">
            $(document).ready(function()
                {
                    $('.FOO').live("click", function (){alert("It Works!")});
                    var $dialog = $('<div></div>').html('<div id="container"><input type ="button" id="CUSTOM" value="click"/>This dialog will show every time!</div>').dialog({
                                                                                                         autoOpen: false,
                                                                                                         tite: 'Basic Dialog'
                                                                                                     });
                    $('#theButton').click(function()
                    {
                        $dialog.dialog('open');
                        return('false');
                    });
                    $('#CUSTOM').click(function(){
                        //$('#container').append('<input type="button" value="clickmee" class="FOO" /></br>');
                        var button = document.createElement("input");
                        button.setAttribute('class','FOO');
                        button.setAttribute('type','button');
                        button.setAttribute('value','CLICKMEE');
                        $('#container').append(button);
                    });
                    /* $('#FOO').click(function(){
                                                     alert("It Works!");
                                                 }); */
            });
        </script>
    </body>
</html>

22

선택기를 사용하는 것을 선호하며 문서에 적용합니다.

이것은 문서에 바인딩되며 페이지로드 후 렌더링 될 요소에 적용됩니다.

예를 들면 다음과 같습니다.

$(document).on("click", 'selector', function() {
    // Your code here
});

2
선택자는 $로 묶지 말아야하므로 올바른 형식은 $ (document) .on ( "click", "selector", function () {// Your code here});
자동 조종 장치

1
selector변수에 문자열이나 Element 객체를 포함해야 할 때 jQuery 객체를 변수 로 감싸는 것도 의미가 없습니다.on()
Rory McCrossan

20

다른 해결책은 요소를 만들 때 리스너를 추가하는 것입니다. 리스너를 본문에 넣는 대신 리스너를 만드는 순간 리스너를 요소에 넣습니다.

var myElement = $('<button/>', {
    text: 'Go to Google!'
});

myElement.bind( 'click', goToGoogle);
myElement.append('body');


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}

코드에 1 개의 실수 myElement.append('body');가 있습니다 myElement.appendTo('body');. 반면에 변수를 더 이상 사용할 필요가 없다면 다음 myElement과 같이 더 쉽고 짧습니다.$('body').append($('<button/>', { text: 'Go to Google!' }).bind( 'click', goToGoogle));
ddlab


16

예를 들어, 요소가 배치 된 "MAIN"클래스에 유의하십시오.

<div class="container">
     <ul class="select">
         <li> First</li>
         <li>Second</li>
    </ul>
</div>

위 시나리오에서 jQuery가 볼 MAIN 객체는 "컨테이너"입니다.

그러면 기본적으로 컨테이너 아래 ulli, 및 같은 요소 이름이 있습니다 select.

$(document).ready(function(e) {
    $('.container').on( 'click',".select", function(e) {
        alert("CLICKED");
    });
 });

14

당신은 사용할 수 있습니다

$('.buttons').on('click', 'button', function(){
    // your magic goes here
});

또는

$('.buttons').delegate('button', 'click', function() {
    // your magic goes here
});

이 두 방법은 동일하지만 매개 변수 순서가 다릅니다.

참조 : jQuery 위임 이벤트


2
delegate()더 이상 사용되지 않습니다. 사용하지 마십시오.
Rory McCrossan

14

을 사용하여 동적으로 만들 때 요소에 이벤트를 첨부 할 수 있습니다 jQuery(html, attributes).

jQuery 1.8부터는 모든 jQuery 인스턴스 메소드 (의 메소드 jQuery.fn)를 두 번째 매개 변수에 전달 된 객체의 속성으로 사용할 수 있습니다.

function handleDynamicElementEvent(event) {
  console.log(event.type, this.value)
}
// create and attach event to dynamic element
jQuery("<select>", {
    html: $.map(Array(3), function(_, index) {
      return new Option(index, index)
    }),
    on: {
      change: handleDynamicElementEvent
    }
  })
  .appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>


14

이것은 이벤트 위임에 의해 수행됩니다 . 이벤트는 랩퍼 클래스 요소에 바인드되지만 선택기 클래스 요소에 위임됩니다. 이것이 작동하는 방식입니다.

$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});

노트 :

래퍼 클래스 요소는 ex 일 수 있습니다. 문서, 본문 또는 포장지. 랩퍼가 이미 존재해야합니다 . 그러나 selector페이지로드시 반드시 제시 될 필요는 없습니다. 나중에 올 수 있으며 이벤트는 selector 실패없이 바인드됩니다 .


11

동적으로 생성 된 요소가 클릭에 응답하지 않는 이유는 다음과 같습니다.

var body = $("body");
var btns = $("button");
var btnB = $("<button>B</button>");
// `<button>B</button>` is not yet in the document.
// Thus, `$("button")` gives `[<button>A</button>]`.
// Only `<button>A</button>` gets a click listener.
btns.on("click", function () {
  console.log(this);
});
// Too late for `<button>B</button>`...
body.append(btnB);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

이 문제를 해결하려면 모든 클릭을 듣고 소스 요소를 확인해야합니다.

var body = $("body");
var btnB = $("<button>B</button>");
var btnC = $("<button>C</button>");
// Listen to all clicks and
// check if the source element
// is a `<button></button>`.
body.on("click", function (ev) {
  if ($(ev.target).is("button")) {
    console.log(ev.target);
  }
});
// Now you can add any number
// of `<button></button>`.
body.append(btnB);
body.append(btnC);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

이것을 "이벤트 위임"이라고합니다. 좋은 소식은 jQuery의 내장 기능입니다 :-)

var i = 11;
var body = $("body");
body.on("click", "button", function () {
  var letter = (i++).toString(36).toUpperCase();
  body.append($("<button>" + letter + "</button>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>


10

모든 페이지에 존재하는이 arent 이벤트가 바인딩되는 시간과 페이지가 된 경우 동적 요소를 생성하는 클래스 이름을 가진 버튼을 이미 존재하는 부모에 이벤트를 바인딩 할 것

$(document).ready(function(){
  //Particular Parent chield click
  $(".buttons").on("click","button",function(){
    alert("Clicked");
  });  
  
  //Dynamic event bind on button class  
  $(document).on("click",".button",function(){
    alert("Dymamic Clicked");
  });
  $("input").addClass("button");  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="buttons">
  <input type="button" value="1">
  <button>2</button>
  <input type="text">
  <button>3</button>  
  <input type="button" value="5">  
  </div>
<button>6</button>


7

이미 존재하는 부모에게 이벤트를 바인딩하십시오.

$(document).on("click", "selector", function() {
    // Your code here
});


3

이벤트 리스너를 document레벨 이벤트 리스너를 스크립팅하는 대신 모듈 식 기능 방식으로 배치하는 것이 좋습니다 . 그래서 나는 아래를 좋아한다. 동일한 이벤트 리스너로 요소를 초과 구독 할 수 없으므로 리스너를 두 번 이상 연결하는 것에 대해 걱정할 필요가 없습니다.

var iterations = 4;
var button;
var body = document.querySelector("body");

for (var i = 0; i < iterations; i++) {
    button = document.createElement("button");
    button.classList.add("my-button");
    button.appendChild(document.createTextNode(i));
    button.addEventListener("click", myButtonWasClicked);
    body.appendChild(button);
}

function myButtonWasClicked(e) {
    console.log(e.target); //access to this specific button
}


나는이 구현을 선호한다; 난 그냥 전화를 다시 설정해야
윌리엄

3

요소를 만들고 이벤트를 바인딩하는 또 다른 유연한 솔루션 ( source )

// creating a dynamic element (container div)
var $div = $("<div>", {id: 'myid1', class: 'myclass'});

//creating a dynamic button
 var $btn = $("<button>", { type: 'button', text: 'Click me', class: 'btn' });

// binding the event
 $btn.click(function () { //for mouseover--> $btn.on('mouseover', function () {
    console.log('clicked');
 });

// append dynamic button to the dynamic container
$div.append($btn);

// add the dynamically created element(s) to a static element
$("#box").append($div);

참고 : 이렇게하면 각 요소에 대한 이벤트 핸들러 인스턴스가 작성 됩니다 (루프에서 사용될 때 성능에 영향을 줄 수 있음)


0
<html>
    <head>
        <title>HTML Document</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    </head>

    <body>
        <div id="hover-id">
            Hello World
        </div>

        <script>
            jQuery(document).ready(function($){
                $(document).on('mouseover', '#hover-id', function(){
                    $(this).css('color','yellowgreen');
                });

                $(document).on('mouseout', '#hover-id', function(){
                    $(this).css('color','black');
                });
            });
        </script>
    </body>
</html>

3
이 코드 스 니펫은 문제를 해결할 수 있지만 질문에 왜 또는 어떻게 대답하는지는 설명하지 않습니다. 게시물의 품질을 향상시키는 데 도움이되는 코드에 대한 설명을 포함하십시오. 앞으로 독자들에게 질문에 대한 답변을 제공하므로 해당 사람들이 코드 제안의 이유를 모를 수도 있습니다.
Palec

0

동적으로 추가 된 요소에서 문제없이 작업 $.bind하고 $.unbind작업 할 수있는 솔루션을 찾고있었습니다 .

on ()과 같이 이벤트를 첨부하는 트릭을 만들면 내가 온 사람들에게 가짜 바인딩을 만들 수 있습니다.

const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction );

// unbind the click
$('body').on('click', 'button.send', function(){} );

바인딩 해제가 작동하지 않습니다. 이것은 단순히 빈 함수를 가리키는 다른 이벤트를 추가합니다.
Fabian Bigler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.