การเชื่อมโยงเหตุการณ์กับองค์ประกอบที่สร้างแบบไดนามิก?

Oct 15 2008

ฉันมีบิตของรหัสที่ฉันกำลังบ่วงผ่านทุกช่องเลือกบนหน้าเว็บและผูกพัน.hoverเหตุการณ์ที่พวกเขาทำบิตของ twiddling mouse on/offที่มีความกว้างของพวกเขาใน

สิ่งนี้เกิดขึ้นในหน้าที่พร้อมและใช้งานได้ดี

ปัญหาที่ฉันมีคือกล่องเลือกใด ๆ ที่ฉันเพิ่มผ่าน Ajax หรือ DOM หลังจากลูปเริ่มต้นจะไม่มีเหตุการณ์ที่ผูกไว้

ฉันพบปลั๊กอินนี้ ( jQuery Live Query Plugin ) แต่ก่อนที่ฉันจะเพิ่ม 5k ในหน้าของฉันด้วยปลั๊กอินฉันต้องการดูว่ามีใครรู้วิธีทำสิ่งนี้ไม่ว่าจะด้วย jQuery โดยตรงหรือโดยตัวเลือกอื่น

คำตอบ

2335 Popnoodles Jul 30 2009 at 22:34

สำหรับ jQuery 1.7คุณควรใช้jQuery.fn.onกับพารามิเตอร์ตัวเลือกที่เต็มไป:

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

คำอธิบาย:

สิ่งนี้เรียกว่าการมอบหมายเหตุการณ์และทำงานดังต่อไปนี้ เหตุการณ์ถูกแนบกับแม่แบบคงที่ ( staticAncestors) ขององค์ประกอบที่ควรจัดการ ตัวจัดการ jQuery นี้จะถูกทริกเกอร์ทุกครั้งที่เหตุการณ์ทริกเกอร์บนองค์ประกอบนี้หรือหนึ่งในองค์ประกอบที่สืบทอด จากนั้นตัวจัดการจะตรวจสอบว่าองค์ประกอบที่ทริกเกอร์เหตุการณ์ตรงกับตัวเลือกของคุณ ( dynamicChild) หรือไม่ เมื่อมีการจับคู่ฟังก์ชันตัวจัดการที่กำหนดเองของคุณจะถูกเรียกใช้งาน


ก่อนหน้านี้แนวทางที่แนะนำคือให้ใช้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>
388 RonenRabinovici Aug 09 2013 at 16:51

มีคำอธิบายที่ดีในเอกสารของ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

231 RamPatra Dec 09 2014 at 14:59

นี่เป็นโซลูชัน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);
}
76 nickf Oct 15 2008 at 06:31

คุณสามารถเพิ่มเหตุการณ์ให้กับออบเจ็กต์เมื่อสร้างได้ หากคุณกำลังเพิ่มเหตุการณ์เดียวกันให้กับวัตถุหลายชิ้นในเวลาที่ต่างกันการสร้างฟังก์ชันที่มีชื่ออาจเป็นหนทางที่จะไป

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 */ )
;
51 GregBorenstein Oct 15 2008 at 06:35

คุณสามารถรวมการเรียกการผูกเหตุการณ์ของคุณลงในฟังก์ชันแล้วเรียกใช้สองครั้ง: หนึ่งครั้งในเอกสารพร้อมและหนึ่งครั้งหลังจากเหตุการณ์ของคุณที่เพิ่มองค์ประกอบ DOM ใหม่ หากคุณทำเช่นนั้นคุณจะต้องหลีกเลี่ยงการผูกเหตุการณ์เดียวกันสองครั้งกับองค์ประกอบที่มีอยู่ดังนั้นคุณจะต้องเลิกผูกเหตุการณ์ที่มีอยู่หรือ (ดีกว่า) เฉพาะการเชื่อมโยงกับองค์ประกอบ DOM ที่สร้างขึ้นใหม่ รหัสจะมีลักษณะดังนี้:

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

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

// ... add elements ...
addCallbacks($(".myNewElements"))
43 user670265 Mar 22 2011 at 05:35

พยายามใช้.live()แทน.bind(); .live()จะผูก.hoverจะทำเครื่องหมายในช่องของคุณหลังจากที่อาแจ็กซ์รันคำขอ

32 MadeInDreams Jan 22 2016 at 08:06

การเชื่อมโยงเหตุการณ์กับองค์ประกอบที่สร้างขึ้นแบบไดนามิก

องค์ประกอบเดียว:

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

องค์ประกอบของเด็ก:

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

*ขอให้สังเกตที่เพิ่ม เหตุการณ์จะถูกทริกเกอร์สำหรับชายด์ทั้งหมดขององค์ประกอบนั้น

ฉันสังเกตเห็นว่า:

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

มันไม่ทำงานอีกต่อไป แต่ก่อนหน้านี้ใช้งานได้ ฉันใช้ jQuery จาก Google CDNแต่ฉันไม่รู้ว่าพวกเขาเปลี่ยนหรือไม่

27 Fazi Dec 21 2011 at 14:26

คุณสามารถใช้เมธอด 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>
27 Vatsal Nov 21 2015 at 19:01

ฉันชอบใช้ตัวเลือกและใช้กับเอกสาร

สิ่งนี้จะผูกมัดตัวเองกับเอกสารและจะใช้ได้กับองค์ประกอบที่จะแสดงผลหลังจากการโหลดหน้า

ตัวอย่างเช่น:

$(document).on("click", 'selector', function() {
    // Your code here
});
22 MartinDaRosa Oct 08 2015 at 00:43

อีกวิธีหนึ่งคือการเพิ่ม Listener เมื่อสร้างองค์ประกอบ แทนที่จะให้ผู้ฟังอยู่ในเนื้อความคุณต้องใส่ผู้ฟังไว้ในองค์ประกอบในช่วงเวลาที่คุณสร้างมันขึ้นมา:

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

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


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}
20 RohitSuthar Jun 30 2016 at 13:25

ลองทำแบบนี้ -

$(document).on( 'click', '.click-activity', function () { ... });
20 MustkeemK Jun 14 2018 at 18:15

นี้จะกระทำโดยคณะผู้แทนเหตุการณ์ เหตุการณ์จะได้รับการผูกกับองค์ประกอบของ Wrapper-class แต่จะถูกมอบหมายให้กับองค์ประกอบ Selector-class นี่คือวิธีการทำงาน

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

และ HTML

<div class="wrapper-class">
    <button class="selector-class">
      Click Me!
    </button>
</div>    

# หมายเหตุ: องค์ประกอบของ wrapper-class สามารถเป็นอะไรก็ได้เช่น เอกสารเนื้อหาหรือกระดาษห่อหุ้มของคุณ Wrapper ควรมีอยู่แล้ว อย่างไรก็ตามselectorไม่จำเป็นต้องนำเสนอในเวลาโหลดหน้าเว็บ มันอาจจะมาในภายหลังและเหตุการณ์จะผูกบนโดยไม่ต้องล้มเหลวselector

17 AslanKaya Mar 26 2016 at 09:15

จดคลาส "MAIN" ที่วางองค์ประกอบไว้เช่น

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

ในสถานการณ์ข้างต้นออบเจ็กต์ MAIN ที่ jQuery จะรับชมคือ "คอนเทนเนอร์"

จากนั้นคุณโดยทั่วไปจะมีชื่อองค์ประกอบภายใต้ภาชนะเช่นul, liและselect:

$(document).ready(function(e) { $('.container').on( 'click',".select", function(e) {
        alert("CLICKED");
    });
 });
15 MensurGrišević Aug 11 2016 at 23:16

คุณสามารถใช้

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

หรือ

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

สองวิธีนี้เทียบเท่ากัน แต่มีลำดับพารามิเตอร์ต่างกัน

ดู: jQuery Delegate Event

15 guest271314 Apr 05 2017 at 14:11

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>

12 leaf Sep 16 2017 at 14:01

นี่คือสาเหตุที่องค์ประกอบที่สร้างแบบไดนามิกไม่ตอบสนองต่อการคลิก:

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>

11 AnkitKathiriya Dec 18 2015 at 15:48

p ใด ๆที่ไม่มีอยู่ในเวลาที่เหตุการณ์ถูกผูกไว้และหากเพจของคุณสร้างองค์ประกอบแบบไดนามิกด้วยปุ่มชื่อคลาสคุณจะผูกเหตุการณ์กับพาเรนต์ที่มีอยู่แล้ว

$(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>

10 truongnm Jun 08 2018 at 09:29

ผูกเหตุการณ์กับพาเรนต์ที่มีอยู่แล้ว:

$(document).on("click", "selector", function() {
    // Your code here
});
5 KalpeshPatel Nov 30 2016 at 16:07

ใช้.on()วิธีการของ jQueryhttp://api.jquery.com/on/ เพื่อแนบตัวจัดการเหตุการณ์กับองค์ประกอบที่มีชีวิต

.live()วิธีที่เป็นเวอร์ชัน 1.9 จะถูกลบออกด้วย

5 PrasadDeSilva Apr 19 2017 at 02:47

อีกวิธีที่ยืดหยุ่นในการสร้างองค์ประกอบและเชื่อมโยงเหตุการณ์ (ที่มา )

// 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);

หมายเหตุ: สิ่งนี้จะสร้างอินสแตนซ์ตัวจัดการเหตุการณ์สำหรับแต่ละองค์ประกอบ (อาจส่งผลต่อประสิทธิภาพเมื่อใช้ในลูป)

4 RonnieRoyston Jun 08 2018 at 09:53

ฉันชอบที่จะให้ผู้ฟังเหตุการณ์ใช้งานในรูปแบบของฟังก์ชันโมดูลาร์มากกว่าการเขียนสคริปต์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
}

FakhrulHasan Sep 27 2017 at 22:42
<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>
Evhz May 18 2018 at 07:13

ฉันกำลังมองหาวิธีแก้ปัญหาเพื่อรับ$.bindและ$.unbindทำงานโดยไม่มีปัญหาในองค์ประกอบที่เพิ่มแบบไดนามิก

ตามที่ ()สร้างเคล็ดลับในการแนบเหตุการณ์เพื่อสร้างการเลิกผูกปลอมกับสิ่งที่ฉันมา:

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