ràng buộc sự kiện chỉ một lần


Câu trả lời:


190

Nếu bạn có thể áp dụng nó, có thể bạn muốn xem qua event.preventDefaultevent.stopPropagation HOẶC bỏ liên kết và ràng buộc mỗi lần, trong phương pháp của bạn như

function someMethod()
{
  $(obj).off('click').on('click', function(e) {
    // put your logic in here 
  });
}

19
Hãy cẩn thận, vì điều này hủy liên kết TẤT CẢ các sự kiện nhấp chuột và không phải lúc nào nó cũng là hành vi mong muốn. Ví dụ: khi bạn liên kết một cái gì đó với tài liệu, bạn chỉ muốn hủy liên kết một sự kiện đó, không phải tất cả chúng.
Mārtiņš Briedis,

26
Trong trường hợp bạn không muốn vô tình unbind sự kiện nhấp chuột khác, bạn có thể muốn sử dụng function someMethod() { $(obj).off('click.namespace').on('click.namespace', function {}); }
Manu

@Manu bạn đã sao chép từ câu trả lời này
aexl

89

Ngoài câu trả lời của pna, bạn có thể muốn suy nghĩ về việc đặt tên cho sự kiện của mình để bạn không vô tình bỏ liên kết tất cả các sự kiện nhấp chuột.

function someMethod () {
    $ (obj) .unbind ('click.namespace'). bind ('click.namespace', function () {});
}

https://api.jquery.com/event.namespace/


10
Đây phải là câu trả lời được chấp nhận. Việc hủy liên kết tất cả các sự kiện nhấp chuột có thể dễ dàng phá vỡ mọi thứ - đặc biệt nếu nó là một dự án phức tạp với nhiều jQuery đang diễn ra. Cảm ơn vì điều đó! Không biết về giải pháp không gian tên đơn giản này !!
Simon Steinberger

Với jQuery hiện tại, điều này phải là $(obj).off()$(obj).on()tương ứng. Nếu không, không gian tên đã giúp và điều này đã hoạt động. Cảm ơn bạn!
aexl

19

Không có phương pháp cài sẵn nào để xác định xem bạn đã ràng buộc hàm cụ thể này chưa. Bạn có thể liên kết nhiều hàm bấm vào một đối tượng. Ví dụ:

$('#id').bind('click', function(){
alert('hello');
});


$('#id').bind('click', function(){
alert('goodbuy');
});

nếu bạn làm như trên khi đối tượng được nhấp vào nó sẽ cảnh báo xin chào rồi tạm biệt. Để đảm bảo chỉ một hàm được liên kết với sự kiện nhấp chuột, hãy bỏ liên kết trình xử lý sự kiện nhấp, sau đó ràng buộc chức năng mong muốn như sau:

$(obj).unbind('click').bind('click', function(){... });

12

Giải pháp rõ ràng là không gọi someMethod()hai lần. Nếu bạn không thể khắc phục điều đó, thì bạn có thể giữ một biến trạng thái để nó chỉ liên kết một lần như thế này:

function someMethod()
{
    if (!someMethod.bound) {
        $(obj).click(function() {});
        someMethod.bound = true;
    }
}

Lưu ý: điều này sử dụng một thuộc tính của chính hàm thay vì giới thiệu một biến toàn cục để theo dõi xem nó có bị ràng buộc hay không. Bạn cũng có thể sử dụng một thuộc tính trên chính đối tượng.

Bạn có thể thấy nó hoạt động tại đây: http://jsfiddle.net/jfriend00/VHkxu/ .


11

Hoặc sử dụng hàm one () của jQuery tương tự như on () nhưng chỉ kích hoạt sự kiện một lần, ngay cả khi bạn liên kết sự kiện nhiều lần.

http://api.jquery.com/one/


8
Đôi khi nó có ích. nhưng đôi khi bạn muốn giải pháp mà bạn có thể: ĐẠT MỘT LẦN NHƯNG SỬ DỤNG NHIỀU.
Rzassar

5

jQuery làm cho việc gọi một số hàm có thể chỉ một lần khá dễ dàng:

function someMethod()
{

     $(obj).click(function() {});
      this.someMethod = $.noop;
}

1
Điều này sẽ chỉ hoạt động nếu someMethod là phương thức của một đối tượng hoặc hàm toàn cục.
jcubic

jQuery.noopchỉ ngắn hơn một ký tự function(){}, vì vậy thật ngớ ngẩn khi nói rằng nó đang "giúp đỡ" ở đây, chỉ cung cấp một hàm trống. Đây là một ví dụ không phải phương thức jQuery về giải pháp chung này:var fn = function(){ fn = function(){}; do stuff; };
1j01

1
@ 1j01 Đã chỉnh sửa để sử dụng $thay thế
Esailija 27/02/15

2

Đây là một gợi ý vì tôi không biết logic của bạn. Có thể có hoặc có thể không phù hợp với bạn.

Hãy thử kết hợp hàm jquery live () và một () sẽ cho bạn kết quả tốt hơn so với sự kiện rebinds.

Các trường hợp đặc biệt hoạt động khi bạn có 2 phần tử DOM (cha và con). Live () tại nút cha đảm bảo rằng sự kiện sẽ được gọi và sau đó gọi một () để đăng ký động sự kiện sẽ chỉ được thực thi một lần. (điều này cung cấp chức năng tương tự như rebinds).


One()chức năng hoạt động trong chromenhưng không hoạt động safaritrong Mac.
Half Blood Prince

2

Bạn có thể thêm lớp css vào các phần tử được liên kết và sau đó lọc chúng ra:

function someMethod()
{
    $(obj).not('.click-binded')
          .click(function {})
          .addClass('click-binded');
}

Phương pháp này cũng có thể được sử dụng cho các plugin:

  $(obj).not('.datetimepicker-applied')
        .datetimepicker()
        .addClass('datetimepicker-applied');

1
var bound = false;

function someMethod()
{
    if(!bound)
    {
       $(obj).click(function {});
       bound = true;
    }
}

nhưng tôi có lẽ sẽ xem xét tại sao nó được gọi hai lần trước khi thực hiện một số loại giải pháp.


3
Nếu bạn đang đi theo hướng này, hãy xem xét giải pháp của jfriend00 boundđể gắn vào someMethod()thay vì gây ô nhiễm không gian tên toàn cầu.
nuala

1

Nếu bạn chỉ muốn liên kết với đối tượng một lần, bạn nên triển khai một cờ và dính vào đối tượng đó.

Ví dụ:

if($('#id') && $('#id').data('done') == null)) {
    $('#id').bind('click', function() {
        alert('hello');
    });

    $('#id').data('done', true);
}

1

Bạn có thể sử dụng chức năng mở rộng jQuery này.

$.fn.once = function (type, fn, uid) {
  if(uid == undefined) {
    console.error("Called $.once without uid\n", this, "\n", fn);
  }

  var dataStr = type+"-handler-"+uid;
  if(!this.data(dataStr)) {
    this.data(dataStr, true);
    this.on(type, fn);
  }
};

Thay vì làm điều này

$("button").on("click", function(){
  alert("You Clicked On A Button");
});

Ya làm điều này

$("button").once("click", function(){
  alert("You Clicked On A Button");
}, "btnHandler");

Bây giờ khi tôi có một chức năng xung quanh nó

function addBtnHandler() {
  $("button").once("click", function() {
    alert("You Clicked On A Button");
  }, "btnHandler");
}

Và tôi gọi nó nhiều lần

addBtnHandler();
addBtnHandler();
addBtnHandler();

Nó chỉ làm điều đó một lần.

Lưu ý rằng tiện ích mở rộng hoạt động bằng cách kiểm tra cả uid và type. Điều này có nghĩa là bạn có thể liên kết các loại trình xử lý khác nhau với cùng một uid, bạn có thể muốn hoặc không. Để thay đổi nó, hãy chỉnh sửa.

var dataStr = type+"-handler-"+uid;

Với một cái gì đó như

var dataStr = "handler-"+uid;


1

Tôi cũng đang cố gắng sử dụng tắt và bật phương thức jquery cho sự kiện ràng buộc chỉ một lần với phần tử dom chưa tồn tại hoặc phần tử dom chưa được tạo.

$('.select').off('event').on('event', 'selector', function(e){ // });

Mã này không hoạt động bình thường

Tôi đã bắt gặp một phương pháp rất sinh lợi đó là phương pháp 'một'. Nó rất hữu ích khi bạn chỉ muốn ràng buộc một sự kiện một lần.

Bạn có thể tìm thấy tài liệu tại đây http://api.jquery.com/one/

Phương thức này giống với phương thức 'on' nhưng khác với hành vi của nó là không gắn với sự kiện cho nhiều bộ chọn.

$('body').one('click', 'selector', function(){ // do your stuff here });

1

Bạn có thể đạt được điều này với JS thuần túy, sử dụng phương thức addEventListener và tùy chọn một lần của anh ấy

target.addEventListener('click', handler, {once: true});

2
Điều này khiến sự kiện trở nên không bị ràng buộc sau khi phần tử được nhấp một lần. Điều này không giải quyết được vấn đề các sự kiện bị ràng buộc nhiều lần.
Top Cat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.