Используйте цикл для привязки событий

//I hava this tool function to bind event
var bindEvent = function($dom,events,data,_this){
  for(var key in events){
    $dom.bind(key,function(){
      events[key].apply(_this,[data]);
    });
  }
};

//and use like this
var events = {
  click:function(){
    alert("click");
  },
  dblclick:function(){
    alert("dblclick");
  }
};

var $btn = $("#btn");
bindEvent($btn,events,"mydata",$btn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

когда я нажимаю на кнопку, событие dblclick всегда запускается.
Я знаю причину этой проблемы.
При связывании происходит замыкание, которое используется в цикле for. По окончании цикла последний объект в памяти (есть функция обратного вызова dbclick).
Итак, когда триггер click событие, оно работает alert("dblclick"),
Я хочу знать, был ли хороший способ решить эту проблему. Или есть хороший способ реализовать функцию инструмента для события привязки.
Большое спасибо.

5 ответов

Решение

Создать closure внутри for-in петля (при прикреплении event) где inner-function запомнит среду, в которой он создан!

var bindEvent = function($dom, events, data, _this) {
  for (var key in events) {
    $dom.bind(key, (function(key) {
      return function() {
        events[key].apply(_this, [data]);
      }
    })(key));
  }
};
var events = {
  click: function() {
    console.log("click");
  },
  dblclick: function() {
    console.log("dblclick");
  }
};

var $btn = $("#btn");
bindEvent($btn, events, "mydata", $btn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Примечание: как alert вызывается на click событие, dblclick событие предотвращено, используйте console.log вместо alert и проверить!

Я не знаю зачем тебе data, но в целом вам не нужен цикл для добавления более одного события. Вы можете просто передать объект bind или же on, И потому, что в случае this это всегда элемент, вам не нужно устанавливать контекст.

$("#btn").on({
    click: function() {
        console.log("click");
    },
    dblclick: function() {
        console.log("dblclick");
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Или как длинная версия с вашей функцией-оберткой:

var bindEvent = function($dom, events) {
    $dom.bind(events);
};

var events = {
    click: function(){
        console.log("click");
    },
    dblclick: function(){
        console.log("dblclick");
    }
};

var $btn = $("#btn");
bindEvent($btn, events);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Оба события всегда противоречат друг другу, но вы можете достичь этого путем подсчета количества кликов за небольшой промежуток времени.

//I hava this tool function to bind event
var bindEvent = function($dom,events,data,_this){
    $dom.on(events);
  
};
var dblckickinterval = 500, clicks = 0, timer = null;
//and use like this
var events = {
  click:function(e){
   clicks++;  //count clicks

        if(clicks === 1) {
            timer = setTimeout(function() {
                alert("click");  //perform single-click action    
                clicks = 0; //after action performed, reset counter
            }, dblckickinterval);
        } else {

            clearTimeout(timer);    //prevent single-click action
            alert("dblclick");  //perform double-click action
            clicks = 0;             //after action performed, reset counter
        }
    
  },
  dblclick:function(e){
    e.preventDefault();
    
  }
};

var $btn = $("#btn");
bindEvent($btn,events,"mydata",$btn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Попробуй это:

var eventBinder = function(obj, events) {
  $.each(events, function(key, value) {
    obj.on(key, function(e) {
      events[key]();
    });
  });
}

var eventsData = {
  click: function(e) {
    console.log("click");
  },
  dblclick: function(e) {
    console.log("dblclick");
  }
};

eventBinder($("#btn"), eventsData);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Я не знаю точного ответа, но я пытался:

var bindEvent = function(dom,events,data,_this){
    dom.bind(events,function(){
    for(var key in events){
      events[key].apply(_this,[data]);
    }
  });
}
Другие вопросы по тегам