我使用jQuery事件完成了一些发布/订阅。
基本功能有效:
var publish = function(name) { // --- works
var args = Array.prototype.slice.call(arguments); // convert to array
args = args.slice(1); // remove arg1 (name)
$("html").trigger(name, args);
}
var subscribe = function(name, callback) { // --- works
$("html").on(name, callback);
}
var unsubscribe = function(name, callback) { // --- works
$("html").off(name, callback);
}
// usage: // --- works
var myhandler = function () { /* ... */ };
subscribe("foo", myhandler);
publish("foo", 1, false, "bob", {a:1, b:"2"});
unsubscribe("foo", myhandler);
但订阅我想要的方式,不会:
var subscribe = function(name, callback) { // --- can't unsub this
$("html").on(name, function () {
var args = Array.prototype.slice.call(arguments);
args = args.slice(1);
callback.apply(null, args);
});
}
我想要第二个subscribe
函数,因为匿名回调剥离了第一个参数(Event
对象),我不想在" clean"客户代码。我想在回调中收到的只是事件数据,我不想要Event对象本身。
但这意味着我无法成功调用unsubscribe
,因为我没有将off()
传递给传递给on()
的相同回调 - 这不是实际的回调,而是包裹匿名函数。
有解决方法吗?
答案 0 :(得分:2)
通常的方法是使用jQuery的"namespaced" events:
$("html").on(name + ".my-pub-sub", function () {
// ...
});
然后取消订阅:
$("html").off(name + ".my-pub-sub");
告诉jQuery删除具有给定事件名称和特定命名空间的所有处理程序。
这是一个简化的例子:
// Add two click handlers:
$("button").on("click", function() {
$("<p>Non-namespaced click</p>").appendTo(document.body);
});
$("button").on("click.namespace", function() {
$("<p>Namespaced click</p>").appendTo(document.body);
});
// Show they both trigger
$("<p>Clicking...</p>").appendTo(document.body);
$("button").click();
// Remove the namespaced one without a function ref
$("button").off("click.namespace");
// Now just the non-namespaced one runs
$("<p>Clicking again...</p>").appendTo(document.body);
$("button").click();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button>The button</button>
答案 1 :(得分:1)
您可以返回新创建的事件处理程序,如下所示:
var subscribe = function(name, callback) {
var handler = function () {
var args = Array.prototype.slice.call(arguments);
args = args.slice(1);
callback.apply(null, args);
};
$("html").on(name, handler);
return handler;
};
现在您可以像这样使用它:
var myhandler = function () { console.log(arguments); };
var eventHandler = subscribe("foo", myhandler);
publish("foo", 1, false, "bob", {a:1, b:"2"}); // logs to console
unsubscribe("foo", eventHandler);
publish("foo", 1, false, "bob", {a:1, b:"2"}); // don't log anymore
以下是 demo
答案 2 :(得分:0)
我所做的是基于@TJCrowder提出的名称空间构思。但我已经将他的答案标记为谢谢。
var subscribe = function(name, callback) {
// create a unique "key" for this specific event handler
// - use this format: ORIGINALNAME.MILLISECONDS.RANDOMNUMBER
// - include time in random string, as could be lots of subs happening at once
// - then include a random number, just to be safe
var key = name + "." + (new Date().getTime()) + (Math.random()*1000);
$("html").on(key, function () {
var args = Array.prototype.slice.call(arguments);
args = args.slice(1);
callback.apply(null, args);
});
return key;
}
var unsubscribe = function (key) {
$("html").off(key);
};
// usage:
var myhandler = function () { /* ... */ };
var key = subscribe("foo", myhandler);
publish("foo", 1, false, "bob", {a:1, b:"2"});
unsubscribe(key);
由于此密钥是唯一的(好吧,它应该是?!),它只会删除这个特定的处理程序。所以我可以有很多订阅者,只能取消其中一个订阅者。