Используйте цикл для привязки событий
//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]);
}
});
}