#jquery #triggers
#jquery #триггеры
Вопрос:
Этот jsFiddle демонстрирует, о чем я говорю. По сути, я привязываю некоторые элементы к пользовательскому событию, а затем вызываю триггер с помощью
$('*').trigger('myevent', args)
Я делаю это, потому что у меня будут некоторые элементы, привязанные к этому событию, но я пока не знаю, какими они будут, и я хотел бы максимально отделить этот код. Смехотворно дорого вызывать $('*').trigger
или не так дорого, поскольку это вызовет только элементы, которые привязаны к этому событию?
Другими словами, просматривает ли этот код каждый элемент на странице, чтобы увидеть, привязан ли он к этому событию, или он знает, какие из них есть, и просто запускает их? Если верно первое, есть ли лучшее решение?
Комментарии:
1. jQuery создает список всех узлов, соответствующих селектору, затем сообщает им всем, чтобы они запустили событие. Что вы подразумеваете под »
I don't know what they will be yet
«?2. @kevin я имею в виду, что этот код является частью элемента управления, который будет вставлен на различные страницы, которые я хочу привязать к событиям, но я не знаю, какие элементы на этой странице будут привязаны. я хочу создать универсальное решение, к которому нужно подключить несколько триггеров
3. Вы пробовали использовать Firebug для профилирования этого?
Ответ №1:
Лучшим решением является привязка и запуск событий вне документа, поскольку это будет только один элемент DOM:
$(document).bind('myevent', function(e) {});
$(document).trigger('myevent');
Теперь, в конечном счете, кажется, что еще лучшим решением вашей проблемы было бы использовать делегирование событий:
$(document).delegate('.my-delegation-selector', 'myevent', function(e) {
});
Взгляните на этот пример из http://api.jquery.com/delegate /
<!DOCTYPE html>
<html>
<head>
<style>
p { color:red; }
span { color:blue; }
</style>
<script src="http://code.jquery.com/jquery-1.5.js"></script>
</head>
<body>
<p>Has an attached custom event.</p>
<button>Trigger custom event</button>
<span style="display:none;"></span>
<script>
$("body").delegate("p", "myCustomEvent", function(e, myName, myValue){
$(this).text("Hi there!");
$("span").stop().css("opacity", 1)
.text("myName = " myName)
.fadeIn(30).fadeOut(1000);
});
$("button").click(function () {
$("p").trigger("myCustomEvent");
});
</script>
</body>
</html>
Комментарии:
1. или
window
поскольку он не является элементом DOM и содержит всего 6 символов вместо 8 !.2. @eli, дело в том, что я не буду знать, какие элементы будут прикреплены к триггеру. я не могу просто сказать
$(#someelement, #otherelement, #etc).trigger()
. мне нужно что-то общее, что просто запустит событие, и все, что связано с этим событием, сработает3. 1 за решение его актуальной проблемы. @Jason
.live
злой и дорогой. .триггер дешевый.4. @raynos
.live
— зло? как так?5. @Jason ЗЛО! делегирование поиска против работы на SO.
Ответ №2:
Вы думали о pubsub? Что-то столь же простое, как.
(function() {
var $obj = $(window);
window.pub = function(ev, data) {
$obj.trigger(ev, data);
};
window.sub = function(ev, f) {
$obj.bind(ev, f);
};
})();
или удалите зависимость jQuery
(function() {
var $obj = {},
undefined;
window.pub = function(ev, data) {
if ($obj[ev] === undefined) {
return false;
}
for (var i = 0, len = $obj[ev].length; i < len; i ) {
$obj[ev][i](data);
}
};
window.sub = function(ev, f) {
if ($obj[ev] === undefined) {
$obj[ev] = [];
}
$obj[ev].push(f);
};
})();
Оба amplify.subscribe и Backbone.События имеют специальные объекты для этого. Возможно, вы даже найдете другие библиотеки с похожими объектами. Есть даже библиотеки PubSub.js для этого.
Пример:
$("table.sort th").click(function(e) {
...
window.pub("click.sortHeader", e);
});
...
$.fn.pagify = function(json) {
var table = $(this);
...
//enter code here
window.sub("click.sortHeader", function() {
// handle table sorting.
// adjust table pagifying plugin accordingly.
});
};
В общем, pub
есть trigger
и sub
есть bind
. В этом конкретном примере у нас есть два независимых плагина. Они не знают, находятся ли они на одной странице или вообще разговаривают. Но поскольку сортировка «ломает» плагин подкачки в нашей таблице, у нас есть подписка на «событие» сортировки, чтобы исправить нашу подкачку.
Кто-нибудь другой может предложить лучший пример. По сути, это просто способ передачи сообщений без каких-либо предположений о том, существует ли отправитель сообщения или получатель.
Комментарии:
1. я никогда не слышал о pubsub … как это работает? я смотрю на это и понятия не имею, что это должно делать
2. хорошо, я провел некоторое исследование по pubsub, и я думаю, что это именно то, что я хочу. по сути, это способ для отправителя и получателя быть в полном неведении о другом. как приведенный выше код будет работать на практике?
3. @Jason небольшой пример прилагается.
4. спасибо, raynos. это идеально и именно то, что я искал. теперь я могу публиковать мои объекты всем, кто хочет подключиться к ним. потрясающе!
Ответ №3:
Смотрю на исходный код jquery. Когда вы запускаете событие в jQuery, оно проверяет наличие допустимого узла
// don't do events on text and comment nodes
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
return undefined;
}
И позже проверьте наличие действительного обработчика для фактического объекта dom
// Trigger the event, it is assumed that "handle" is a function
var handle = jQuery._data( elem, "handle" );
if ( handle ) {
handle.apply( elem, data );
}
Я думаю, что реальная проблема заключается в использовании селектора $ (‘*’). Попробуйте другое из предложенных решений вашей проблемы
Комментарии:
1. то есть вы хотите сказать, что это дорого делать
$('*').trigger()
?2. @Jason: Я говорю, что дорогостоящая операция связана с выбором всех узлов $ (‘*’), а не с запуском события на каждом из них, потому что не ко всем узлам прикреплен обработчик