2012-08-23 33 views
9

Tôi nhận được kết quả không mong muốn với jQuery đang cố gắng đặt phương thức "nhấp" của div. Vui lòng xem this jsfiddle. Đảm bảo mở cửa sổ bảng điều khiển. Nhấp vào từ vài lần và xem đầu ra của bàn điều khiển. Hàm click được gọi nhiều lần khi nó chỉ được gọi một lần.jquery .click được gọi nhiều lần

Mã nhận xét ở cuối hoạt động tốt. Tôi có làm điều gì sai? Tôi mới sử dụng jQuery.

Dưới đây là các mã:

function toggleDiv(status) 
{ 
    console.log("toggleDiv(" + status + ")"); 
    if (status) { 
     $("#test").html("Goodbye"); 
    } 
    else { 
     $("#test").html("Hello"); 
    } 
    $("#test").click(function() { 
     toggleDiv(!status); 
    }); 

    // Non-jquery method works fine.... 
    //document.getElementById("test").onclick = function() { 
    // toggleDiv(!status); 
    //} 
}​ 

Cập nhật: Dường như có rất nhiều cách để da mèo này. Vấn đề thực sự ở đây là tôi không hiểu rằng chức năng "click" của jQuery có ADDS một trình xử lý khác. Tôi nghĩ rằng nó thay thế trình xử lý hiện tại.

Trả lời

17

Bạn đang thiết lập một .click() eventHandler mới mỗi lần bạn tiếp tục nhấp chuột vào nó (mà lần lượt tạo ra các sự kiện thậm chí nhiều hơn). Trên một lưu ý phụ, cố gắng không bao giờ sử dụng các sự kiện onclick/onmouseover/onmouseout/etc trên các phần tử DOM. Trong Internet explorer những tạo khối kịch bản (mà bạn rõ ràng có thể thấy nếu bạn sử dụng Visual Studio trang với hàng ngàn những hiệu suất xuống chậm rất

Dường như bạn đang cố gắng để đạt được điều này:.!

jsFiddle DEMO

$("#test").on('click', function() { 
    var this$ = $(this), 
     _status = !!this$.data('status'); // force to boolean 
        // ^will default to false since we have no data-status attribute yet 

    this$.html(_status ? 'Hello' : 'Goodbye') 
     .data('status', !_status); 
});​ 
+0

Cảm ơn. Tôi không quen thuộc với thuộc tính "trạng thái dữ liệu" nhưng nó phù hợp với nhu cầu của tôi. Tuy nhiên, lưu ý rằng để mã của bạn hoạt động như chuyển đổi, cần thêm "$ (this) .data ('status', true);" để tuyên bố khác. –

+0

Nếu bạn chỉ muốn thay đổi văn bản đó, bạn nên xem xét câu trả lời của mình, bạn không cần phải sử dụng .data() tại tất cả – kannix

+0

Tại sao bạn trộn $ ("# test") và $ (this)? – kannix

13

Bạn đang đăng ký lại trình xử lý click lặp đi lặp lại một cách đệ quy.

Một giải pháp đúng (của nhiều biến thể) là thế này:

$(function() { 
    var status = false; 

    $('#test').click(function() { 
     status = !status; 
     $(this).html(status ? 'Goodbye' : 'Hello'); 
    }); 
}); 

và sau đó bạn cần phải loại bỏ các thuộc tính onclick từ HTML - nó không tốt để trộn dom0 và sự kiện DOM3 xử lý.

Xem http://jsfiddle.net/alnitak/8aBxp/

+0

+1 để đánh bại tôi quá rồi lol :) –

+0

Cảm ơn. Điều này làm việc quá nhưng tôi nghĩ rằng câu trả lời của mcpDESIGNS phù hợp với nhu cầu của tôi tốt hơn. –

3

nhiều khả năng bạn đang chạy toggleDiv lần mutliple, dẫn đến sự kiện click bị ràng buộc nhiều lần. Bind sự kiện nhấp chuột bên ngoài của toggleDiv chức năng.

var status = false; 
function toggleDiv() 
{ 
    console.log("toggleDiv(" + status + ")"); 
    if (status) { 
     $("#test").html("Goodbye"); 
    } 
    else { 
     $("#test").html("Hello"); 
    } 
    status = !status; 
}​ 
$("#test").click(function() { 
    toggleDiv(status); 
}); 
1

Bạn nên ràng buộc sự kiện click bên ngoài chức năng toggleDiv. Mã hiện tại sẽ đăng ký bộ xử lý sự kiện click mới mỗi khi các phần tử trong $('#test') được nhấp, với tăng trưởng theo cấp số nhân (vì tất cả các trình xử lý click trước đó sẽ tạo một trình xử lý click mới, do đó số lượng trình xử lý sẽ tăng gấp đôi với mỗi nhấp chuột).

+0

không, số lượng trình xử lý sẽ tăng bởi _one_ với mỗi nhấp chuột (tức là tuyến tính) – Alnitak

+0

@Alnitak: Tôi đã kiểm tra qua bảng điều khiển. Số lần toggleDiv được gọi (tương đương với số lần sự kiện nhấp được đăng ký) tăng gấp đôi mỗi lần nhấp. – nhahtdh

+0

ah vâng, vậy là vậy. Xin lỗi. – Alnitak

1

Sau nếu bạn, bạn đang thêm một sự kiện nhấp chuột khác vào #test. Nó sẽ gọi tất cả các trình xử lý nhấp chuột khi được nhấp. Có thể bạn không cần điều đó chút nào vì onclick được định nghĩa trong html.

5

Hàm nhấp chuột jQuery không ghi đè lên trình xử lý nhấp chuột trước đó mà thay vào đó thêm trình xử lý mới vào hàng đợi. Vì vậy, khi nhấp chuột được gọi lại, trình xử lý nhấp chuột mới được thêm cùng với tất cả các trình xử lý cũ.

Để ngăn chặn điều này, bạn chỉ cần xóa các trình xử lý cũ trước khi xác định trình xử lý mới.

function toggleDiv(status) 
{ 
    console.log("toggleDiv(" + status + ")"); 
    if (status) { 
     $("#test").html("Goodbye"); 
    } 
    else { 
     $("#test").html("Hello"); 
    } 

    $("#test").unbind(); 

    $("#test").click(function() { 
     toggleDiv(!status); 
    }); 
}​ 

Bạn cũng có thể muốn xem .toggle() event handler.

CẬP NHẬT: Để được rõ ràng hơn về .toggle(), điều này cũng sẽ làm những gì bạn muốn:

$("#test").toggle(
    function(event) { $(event.target).html("Goodbye"); }, 
    function(event) { $(event.target).html("Hello"); } 
); 
+0

Tôi sẽ xem xét chuyển đổi(). Nó có thể là những gì tôi cần. –

+0

Tôi đã thêm bản cập nhật với mẫu mã sẽ giúp bạn. –

1

Giải pháp sạch sẽ này: http://jsfiddle.net/kannix/fkMf9/4/

$("#test").click(function() { 
    $(this).text(($(this).text() == "Hello") ? "Goodbye" : "Hello"); 
}); 
+0

Cảm ơn. Điều này làm việc nhưng không cho dự án của tôi. Các jsfiddle chỉ là một ví dụ tầm thường để thử nghiệm. –

1

Vấn đề tương tự đã xảy ra với tôi . Câu trả lời của Joseph Erickson về unbind() hoạt động. Nếu trợ giúp, dưới đây là tóm tắt về cách sự kiện onclick kết thúc được gọi nhiều lần trong mã của tôi:

  • Cuộc gọi AJAX đang cập nhật bảng của một người. Nội dung tbody là hoàn toàn năng động.
  • Các hàng trong bảng được truy xuất hàng loạt (thông qua bắt bên máy chủ).
  • Dữ liệu bảng cụ thể (td) có siêu liên kết có sự kiện nhấp chuột liên kết với nó. (Sự kiện nhấp được thêm làm một phần của chức năng gọi lại AJAX)
  • Hiện tại, mọi AJAX được gọi, một sự kiện nhấp liên quan đến td.
  • Do đó, nhiều lần, AJAX được gọi, nhiều trình xử lý nhấp chuột đã được đính kèm vào td.

Tôi đã giải quyết vấn đề này theo đề xuất của Joseph Erickson. Trong cuộc gọi lại AJAX, tôi làm điều này ngay bây giờ: $ (". MsgLinkDiv"). Unbind(); (".msgLinkDiv"). Bấm (hàm (e) {làm công cụ của tôi});

Các vấn đề liên quan