Câu hỏi Sự kiện ràng buộc trên các yếu tố được tạo động?


Tôi có một chút mã nơi tôi đang lặp qua tất cả các hộp chọn trên một trang và ràng buộc .hover sự kiện để họ làm một chút twiddling với chiều rộng của họ trên mouse on/off.

Điều này xảy ra trên trang đã sẵn sàng và hoạt động tốt.

Vấn đề tôi có là bất kỳ hộp chọn nào tôi thêm qua Ajax hoặc DOM sau vòng lặp ban đầu sẽ không có sự kiện bị ràng buộc.

Tôi đã tìm thấy plugin này (Plugin truy vấn trực tiếp jQuery), nhưng trước khi tôi thêm 5k khác vào các trang của mình bằng một plugin, tôi muốn xem liệu có ai biết cách thực hiện điều này hay không bằng jQuery trực tiếp hoặc bằng một tùy chọn khác.


1679
2017-10-14 23:25


gốc


Đây là bài viết chi tiết về cách liên kết sự kiện nhấp chuột cho yếu tố động goo.gl/zlEbnv - Satinder singh


Các câu trả lời:


Tính năng jQuery 1.7 bạn nên sử dụng jQuery.fn.on:

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

Trước đây, cách tiếp cận được khuyến nghị là sử dụng live():

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

Tuy nhiên, live() đã không được chấp thuận trong 1,7 ủng hộ on()và bị xóa hoàn toàn sau 1.9. Các live() Chữ ký:

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

... có thể được thay thế bằng những điều sau on() Chữ ký:

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

Ví dụ: nếu trang của bạn đã tạo động các phần tử với tên lớp dosomething bạn sẽ ràng buộc sự kiện này một phụ huynh đã tồn tại (Đây là vấn đề của vấn đề ở đây, bạn cần một thứ gì đó tồn tại để liên kết, không liên kết với nội dung động), điều này có thể (và tùy chọn dễ nhất) là document. Mặc dù nhớ document có thể không phải là lựa chọn hiệu quả nhất.

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

Bất kỳ phụ huynh nào tồn tại tại thời điểm sự kiện bị ràng buộc đều ổn. Ví dụ

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

sẽ áp dụng cho

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

1791
2017-08-09 09:51



Lưu ý rằng phương thức trực tiếp chỉ hoạt động đối với một số sự kiện nhất định và không phải phương thức khác như nạp dữ liệu. (Xem phần báo trước trong tài liệu.) - Sam Dutton
Tìm hiểu thêm về ủy quyền sự kiện tại đây: learn.jquery.com/events/event-delegation. - Felix Kling
Bất kỳ cách nào để thực hiện điều này với javascript / vanilla js tinh khiết? - Ram Patra
@Ramswaroop bất cứ điều gì bạn có thể làm trong jQuery có thể được thực hiện mà không cần jQuery. Dưới đây là một ví dụ điển hình về ủy quyền sự kiện mà không có jQuery - dave
@ Tôi tự hỏi tại sao câu trả lời bạn chỉ ra không được liệt kê ở đây. Eli đã yêu cầu rõ ràng giải pháp mà không cần bất kỳ plugin nào nếu có thể. - Ram Patra


Có một lời giải thích tốt trong tài liệu của jQuery.fn.on.

Nói ngắn gọn:

Trình xử lý sự kiện chỉ bị ràng buộc với các phần tử hiện được chọn; chúng phải tồn tại trên trang tại thời điểm mã của bạn thực hiện cuộc gọi đến .on().

Như vậy trong ví dụ sau #dataTable tbody tr phải tồn tại trước khi mã được tạo.

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

Nếu HTML mới đang được đưa vào trang, bạn nên sử dụng các sự kiện được ủy quyền để đính kèm một trình xử lý sự kiện, như được mô tả tiếp theo.

Sự kiện được ủy quyền có lợi thế là họ có thể xử lý các sự kiện từ các phần tử con cháu được thêm vào tài liệu sau này. Ví dụ, nếu bảng tồn tại, nhưng các hàng được thêm động bằng cách sử dụng mã, sau đây sẽ xử lý nó:

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

Ngoài khả năng xử lý các sự kiện trên các phần tử con cháu chưa được tạo ra, một ưu điểm khác của các sự kiện được ủy quyền là tiềm năng của chúng cho chi phí thấp hơn nhiều khi nhiều yếu tố phải được giám sát. Trên một bảng dữ liệu với 1.000 hàng trong tbody, ví dụ mã đầu tiên gắn một trình xử lý cho 1.000 phần tử.

Một phương pháp tiếp cận sự kiện được ủy quyền (ví dụ mã thứ hai) gắn một trình xử lý sự kiện cho chỉ một phần tử, tbodyvà sự kiện chỉ cần bong bóng lên một cấp (từ nhấp chuột tr đến tbody).

Chú thích: Sự kiện được ủy quyền không hoạt động cho SVG.


301
2017-12-09 07:59



đây sẽ là một câu trả lời được chấp nhận tốt hơn bởi vì nó sẽ nhanh hơn để ủy nhiệm từ bảng cụ thể hơn là tất cả các cách từ tài liệu (khu vực tìm kiếm sẽ nhỏ hơn nhiều) - msanjay
@msanjay: Mặc dù nhắm mục tiêu tìm kiếm gần hơn với các yếu tố được ưa thích, sự khác biệt về tìm kiếm / tốc độ là rất nhỏ trong thực tế. Bạn sẽ phải bấm 50.000 lần một giây để nhận thấy bất cứ điều gì :) - Gone Coding
Cách tiếp cận này có thể được áp dụng để xử lý các nhấp chuột của hộp kiểm trong một hàng bằng cách thay đổi tr cho một bộ chọn thích hợp, như 'input[type=checkbox]'và điều này sẽ tự động được xử lý cho các hàng mới được chèn vào? - JoeBrockhaus


Đây là một JavaScript thuần túy giải pháp không có bất kỳ thư viện hoặc plugin nào:

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

Ở đâu hasClass Là

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

Bản thử trực tiếp

Tín dụng đi đến Dave và Sime Vidas

Sử dụng JS hiện đại hơn, hasClass có thể được thực hiện như sau:

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

158
2017-10-14 23:31



stackoverflow.com/questions/9106329/… - zloctb
Bạn có thể sử dụng Element.classList thay vì tách - Eugen Konkov
@EugenKonkov Element.classList không được hỗ trợ trên các trình duyệt cũ hơn. Ví dụ, IE <9. - Ram Patra
Một bài viết hay về cách hoàn thành công việc bằng cách sử dụng script vani thay vì jQuery - toddmotto.com/… - Ram Patra
làm thế nào về bubbling? Điều gì xảy ra nếu sự kiện nhấp chuột xảy ra trên con của phần tử bạn quan tâm? - Andreas Trantidis


Bạn có thể thêm sự kiện vào đối tượng khi tạo chúng. Nếu bạn đang thêm các sự kiện tương tự cho nhiều đối tượng vào các thời điểm khác nhau, việc tạo ra một hàm được đặt tên có thể là cách để đi.

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

59
2017-10-14 23:35





Bạn có thể chỉ cần bọc sự kiện ràng buộc sự kiện của mình vào một hàm và sau đó gọi nó hai lần: một lần trên tài liệu đã sẵn sàng và một lần sau sự kiện của bạn thêm các phần tử DOM mới. Nếu bạn làm điều đó, bạn sẽ muốn tránh ràng buộc cùng một sự kiện hai lần trên các phần tử hiện có, do đó bạn sẽ cần hủy liên kết các sự kiện hiện có hoặc (tốt hơn) chỉ liên kết với các phần tử DOM mới được tạo. Mã sẽ trông giống như sau:

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

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

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

40
2018-03-21 22:35



Bài đăng này thực sự đã giúp tôi nắm bắt được vấn đề tôi đang tải biểu mẫu tương tự và nhận được 1,2,4,8,16 ... bài gửi. Thay vì sử dụng .live () Tôi vừa sử dụng .bind () trong hàm gọi .load () của tôi. Đã giải quyết được sự cố. Cảm ơn! - Thomas McCabe


Thử sử dụng .live() thay vì .bind(); các .live() sẽ ràng buộc .hover vào hộp kiểm của bạn sau khi yêu cầu Ajax thực hiện.


37
2017-12-21 07:26



Phương pháp live() đã không được chấp nhận trong phiên bản 1.7 có lợi cho on và bị xóa trong phiên bản 1.9. - chridam


Bạn có thể sử dụng phương thức live () để liên kết các phần tử (ngay cả các phần tử mới được tạo) với các sự kiện và trình xử lý, như sự kiện onclick.

Dưới đây là một mã mẫu tôi đã viết, nơi bạn có thể thấy cách phương thức live () liên kết các phần tử được chọn, thậm chí cả các phần tử mới được tạo, cho các sự kiện:

<!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>

21
2018-01-22 01:06



trực tiếp không được chấp nhận - gorgi93