我正在寫一個jQuery插件,其中啓動/停止插件的事件是可定製的,因此可能相同的事件可以啓動和停止插件(例如點擊開始和點擊停止)。優雅的方式來防止開始後立即停止事件發射
什麼是優雅的方式,非常不涉及超時或解除綁定和聽衆的重新綁定(並沒有太多的「IsPlaying模塊」,「isBeingStarted」標誌等),以確保正確的回調被稱爲
我正在寫一個jQuery插件,其中啓動/停止插件的事件是可定製的,因此可能相同的事件可以啓動和停止插件(例如點擊開始和點擊停止)。優雅的方式來防止開始後立即停止事件發射
什麼是優雅的方式,非常不涉及超時或解除綁定和聽衆的重新綁定(並沒有太多的「IsPlaying模塊」,「isBeingStarted」標誌等),以確保正確的回調被稱爲
最終的解決方案,我已經走了的是爲用於停止和啓動和事件做一個快速的唯一性檢查是否有用於兩個停止,然後啓動任何事件不同的監聽器(這是一個isPlaying檢查)附加到這些。加載插件的性能很小,但在此之後,事件處理代碼的效率大致如此。
function processEvents() {
var tempStart = opts.startEvent.split(" ").sort(),
tempStop = opts.stopEvent.split(" ").sort();
startEventLoop: for(var i=0, il = tempStart.length;i<il;i++) {
for(var j=0, jl = tempStop.length;j<jl;j++) {
if(tempStart[i] == tempStop[j]) {
stopStartEvents.push(tempStart[i])
tempStop.splice(j,1);
continue startEventLoop;
}
}
startEvents.push(tempStart[i])
}
startEvents = startEvents.join(" ");
stopEvents = tempStop.join(" ");
stopStartEvents = stopStartEvents.join(" ");
}
$this.on(stopEvents, function() {
$this.trigger("stop.flickBook");
}).on(startEvents, function() {
$this.trigger("start.flickBook");
}).on(stopStartEvents, function() {
playing ? $this.trigger("stop.flickBook") : $this.trigger("start.flickBook");
});
(注:當我發佈這個答案時,這個問題有一個錯字,這使得它看起來像綁定/解除綁定會沒問題,只要不涉及超時。)
我看不到任何超時,只要適當地結合/解除綁定:
this.bind(startEvent, start);
function start() {
$(this).unbind(startEvent).bind(stopEvent, stop);
}
function stop() {
$(this).unbind(stopEvent).bind(startEvent, start);
}
在上面,我假設startEvent
是配置的開始事件名稱(我可能會添加一個名稱空間,例如,用戶通過"click"
,但添加了".niftyplugin"
,導致startEvent
包含"click.niftyplugin"
,因此您可以隨意綁定/取消綁定),並且stopEvent
是配置的停止事件名稱(帶有名稱空間)。
這裏有一個完整的例子,與命名空間和使用data
記住選項(如果你願意,你可以使用一個閉合) - live copy:
// Plugin stuff
(function($) {
$.fn.niftyPlugin = niftyPlugin;
function niftyPlugin(options) {
var data;
data = {
startEvent: (options && options.startEvent || "click") + ".niftyplugin",
stopEvent: (options && options.stopEvent || "click") + ".niftyplugin"
};
this.data("niftyPlugin", data).bind(data.startEvent, start);
return this;
}
function start() {
var $this = $(this),
data = $this.data("niftyPlugin");
$this.unbind(data.startEvent).bind(data.stopEvent, stop);
display("Start");
}
function stop() {
var $this = $(this),
data = $this.data("niftyPlugin");
$this.unbind(data.stopEvent).bind(data.startEvent, start);
display("Stop");
}
function display(msg) {
$("<p>").html(msg).appendTo(document.body);
}
})(jQuery);
// Use
jQuery(function($) {
$("#theButton").click(function() {
$("<p>Non-plugin hook fired</p>").appendTo(document.body);
}).niftyPlugin({
startEvent: "click"
});
});
唯一的其他替代我看到的是stopImmediatePropagation
- live example:
// Plugin stuff
(function($) {
$.fn.niftyPlugin = niftyPlugin;
function niftyPlugin(options) {
var startEvent, stopEvent, running = false;
startEvent = (options && options.startEvent || "click") + ".niftyplugin";
stopEvent = (options && options.stopEvent || "click") + ".niftyplugin";
this.bind(startEvent, start).bind(stopEvent, stop);
return this;
function start(event) {
if (running) {
return;
}
running = true;
display("Start");
event.stopImmediatePropagation();
}
function stop(event) {
if (!running) {
return;
}
running = false;
display("Stop");
event.stopImmediatePropagation();
}
}
function display(msg) {
$("<p>").html(msg).appendTo(document.body);
}
})(jQuery);
// Use
jQuery(function($) {
$("#theButton").click(function() {
$("<p>Non-plugin hook fired</p>").appendTo(document.body);
}).niftyPlugin({
startEvent: "click"
});
});
我不喜歡它,但是,因爲它與其他的處理程序事件干擾。舉例來說,在上面,如果我改變了沿用到:
// Use
jQuery(function($) {
$("#theButton").niftyPlugin({
startEvent: "click"
}).click(function() {
$("<p>Non-plugin hook fired</p>").appendTo(document.body);
});
});
...這樣的插件抓住非插件代碼,熱潮,非插前的事件在代碼中不會看到事件(example)。
所以,儘管有開銷,我懷疑綁定/解除綁定是你的朋友在這裏。
它可能是矯枉過正,但一個優雅的方式不必保持一堆標誌(例如「isPlaying」)就是使用Finite State Machine。
這裏是一個jQuery實現:https://github.com/DukeLeNoir/jquery-machine
我不太明白這個問題 - 你是說你想阻止人們雙擊一個元素,這會導致你的插件啓動,然後立即停止? – 2011-12-16 15:40:12
當配置設置,使點擊將啓動插件和點擊(即第二次點擊)將停止它,我不想停止處理程序上的第一次點擊 – wheresrhys 2011-12-16 15:42:53