2011-02-07 18 views
28

Có một hàm "unbind" toàn cục trong jQuery, sao cho tôi có thể loại bỏ tất cả các sự kiện bị ràng buộc khỏi một không gian tên đã cho? ví dụ:Làm cách nào để bạn hủy liên kết tất cả các sự kiện jQuery khỏi một không gian tên cụ thể?

// assume these are the events bound to different elements 
$('#foo').bind('click.myNS', ...); 
$('#bar').bind('keyup.myNS', ...); 
$('#baz').bind('dblclick.myNS', ...);  

// magic occurs here... 
$.magicalGlobalUnbindFunction('.myNS'); 

// ...and afterwards, the three binds from above are gone 

Tất cả các ví dụ tôi đã thấy cho unbind yêu cầu một số yếu tố được chọn trước tiên. Tôi đoán rằng về mặt kỹ thuật, bạn có thể làm $('*').unbind('.myNS'), nhưng điều đó có vẻ như rất không hiệu quả.

+0

Tôi không nghĩ HTML có khoảng cách tên, đó là những gì các sự kiện đang bị ràng buộc để. – jondavidjohn

+0

@jondavidjohn: Đây là dạng không gian tên là một cái gì đó được cung cấp bởi jQuery: http://api.jquery.com/bind/ Nó chỉ là một cách để tổ chức các trình xử lý sự kiện để dễ dàng hủy liên kết chúng mà không ảnh hưởng đến bất kỳ ai khác (chẳng hạn như trong một cắm vào). –

+0

@jondavidjohn: không, nhưng với jquery bạn có thể cho một sự kiện không gian tên riêng của nó. Vì vậy, câu hỏi ở đây là "có cách [jquery] để chọn tất cả các sự kiện ràng buộc của không gian tên x" –

Trả lời

13

Bạn có thể thêm myNS làm lớp cho từng yếu tố mà bạn muốn hủy liên kết các sự kiện.

+0

đó là những gì ông nói có vẻ "rất không hiệu quả" – user120242

+0

@ user120242: không, OP cho biết sử dụng * làm công cụ chọn sẽ không hiệu quả, vì về cơ bản nó sẽ tìm và cố gắng hủy liên kết sự kiện khỏi mọi phần tử trên trang. Những gì mikerobi được đề xuất là tại thời điểm ràng buộc, thêm tên lớp cụ thể vào phần tử và sau đó sử dụng tên lớp đó làm công cụ chọn để bạn chỉ chọn các phần tử có liên quan. –

+0

IMO đây có lẽ là giải pháp tốt nhất ... giả sử jquery chưa có thứ gì khác được tích hợp ... mà nó có thể ... trong nội bộ nó giữ một danh sách với không gian tên ... ngay cả khi không có bộ chọn chính thức nào nói "chọn tất cả các phần tử với không gian tên sự kiện này", về mặt lý thuyết sẽ dễ dàng để tạo ra một plugin jquery để làm điều này .. –

4

Thật sự bạn đang tìm kiếm một chức năng toàn cầu huyền diệu nhưng luôn luôn với phép thuật bạn chỉ có thể có ảo ảnh, trong trường hợp này là sự đơn giản.

Ngoài ra còn có giải pháp jQuery sử dụng .live() hoặc .delegate() (chỉ là biến thể của live()).

Sử dụng $("body").delegate("#foo", "click.myNs", func) bạn cũng ràng buộc sự kiện và sử dụng $("#body").undelegate(".myNs") bạn hủy liên kết sự kiện đó. Tôi sử dụng ở đây "cơ thể" phần tử nhưng ofcourse bạn có thể sử dụng bất kỳ yếu tố đó là tổ tiên của tất cả các yếu tố bạn cần ràng buộc trên.

Nó sẽ làm cho "unbinding" của bạn hoạt động nhanh hơn nhưng một lần nữa nó sẽ làm cho sự kiện của bạn phản ứng chậm hơn.

0

Bạn nên thêm một lớp bên trong hàm bind

$('#foo').bind('click.myNS', ...).addClass('removeLater'); 
$('#bar').bind('keyup.myNS', ...).addClass('removeLater'); 
$('#baz').bind('dblclick.myNS', ...).addClass('removeLater'); 

và sau đó

$('.removeLater').unbind(); 

Nếu #foo#bar#etc đều cùng một nguyên tố hoặc nhóm nhỏ trong số họ, bạn cũng có thể làm:

$('div, button').unbind(); 

nhưng tôi f bạn có một sự kiện ràng buộc bạn không muốn loại bỏ đó sẽ không phải là một ý tưởng tốt

3

Bạn cần phải xâm nhập vào internals jQuery, đây là một bản demo làm việc của một thực hiện đơn giản:

http://jsfiddle.net/nkMQv/1/

Công việc chính được thực hiện trong các vòng js thông thường và không nên rất kém hiệu quả vì ngay cả trang này chỉ chứa 106 mục để lặp lại. Tất nhiên, bạn nên sử dụng sự kiện ủy nhiệm càng nhiều càng tốt để giữ số lượng các mục trong bộ sưu tập xử lý jQuery càng nhỏ càng tốt.

+0

+1 Nhưng, chắc chắn là bẩn. – fncomp

+0

Có không gian tên của trình xử lý không may được lưu trữ RẤT sâu trong đối tượng bộ nhớ cache, đó là lý do tại sao có quá nhiều biến vòng lặp bên trong và biến tmp :(Nhưng nếu bạn ẩn đi và chỉ sử dụng phương pháp công khai, bạn sẽ không bao giờ biết mức độ bẩn là – Esailija

+0

Vâng, tôi nghĩ về kỹ thuật của bạn là tốt.Tôi đoán sự khác biệt thực sự giữa các giải pháp của chúng tôi là của tôi có nhiều không gian của bạn sẽ mất nhiều sức mạnh xử lý hơn nữa .. – fncomp

9

Bạn luôn có thể quấn $ .fn.bind và sau đó bộ nhớ cache refs cần thiết:

(function ($) { 
    var origBind = $.fn.bind, 
     boundHash = {}; 

    $.fn.bind = function (type, data, fn) { 
     var namespace = '', 
      events = []; 

     if (typeof type === 'string') { 
      // @todo check the allowed chars for event namespaces. 
      namespace = type.replace(/^[^.]+/, ''); 

      if (namespace.length) { 
       events = boundHash[namespace]; 

       // Namespaces can hold any number of events. 
       events = boundHash[namespace] = $.isArray(events) ? events : []; 

       // Only really need ref to the html element(s)  
       events.push({ 
        type: type, 
        fn: $.isFunction(fn) ? fn : data, 
        that: this.length > 1 ? this.toArray() : this[0] 
       }); 
      } 
     } 

     origBind.apply(this, arguments); 
    }; 

    // namespace to be muffled. Feel free to qualify a specific event type. 
    $.muffle = function (namespace, type) { 
     var events = []; 

     if (boundHash.hasOwnProperty(namespace)) { 
      events = boundHash[namespace]; 

      $.map(events, function (event) { 
       var _type = type || event.type; 

       if (event.type.indexOf(_type) === 0) { 
        $(event.that).unbind(_type, event.fn); 
       } 
      }); 

      // @todo think of better return value. 
      return true; 
     } 

     // @todo think of better return value. 
     return false 
    }; 
})(jQuery); 
+0

Điều tương tự cũng có thể được thực hiện với '.data'. – fncomp

+0

Đẹp. Cái này thật sự rất tốt. Cảm ơn! – CambridgeMike

+0

Tôi đã xóa repo, vì vậy đã xóa nhận xét có liên quan. – fncomp

0

bạn có thể ghi đè lên các phương pháp ràng buộc của jquery và sau đó và trong cửa hàng ghi đè lên một tài liệu tham khảo của tất cả các không gian tên và các sự kiện tương ứng trong một mảng kết hợp và sau đó truy cập vào mảng dựa trên các sự kiện không gian tên mà bạn muốn hủy liên kết. Mã có thể là một cái gì đó như thế này

var eventArray=[]; 
(function ($) { 
    var bind = $.fn.bind; 
    $.fn.bind= function() { 
    var result = bind.apply(this, arguments); 
    var selector=arguments[0]; 
    var nameSpace= selector.split(".")[1]; //code to select the nameSpace eg. click.myNS o/p->myNS (update this if your selector has multiple '.') 
    if(!eventArray[nameSpace]) //if the associative array does not contain the namespace yet 
    { 
     eventArray[nameSpace]=[]; 
    } 
    eventArray[nameSpace].push(selector); 
    return result; 
}; 
})(jQuery); 

Bây giờ với sự kiệnArray với bạn có thể unbind như bạn muốn.Mã để hủy liên kết tất cả các sự kiện trên không gian tên myNS sẽ trông giống như sau:

$.each(eventArray['myNS'],function(){ 
    $(this).unbind(); 
}); 

Hy vọng đây là giải pháp tốt. xin vui lòng cho tôi biết nếu tôi thực hiện bất kỳ sai lầm nào.

4

Bạn cần sử dụng các phương thức OnOff của jQuery. Sử dụng tài liệu làm công cụ chọn.

$(document).off('.myNS'); 

$(document).on('click.myNS','#foo', ...); 
$(document).on('keyup.myNS','#bar', ...); 
$(document).on('dblclick.myNS','#baz','''); 

sau đó phương pháp của bạn có thể trông giống như

$(document).on('click.myNS','#foo', fooClicked); 
var fooClicked = function(e){ 
    var $this = $(e.target); 
    // do stuff 
} 
Các vấn đề liên quan