Обработчики событий

Прямые каналы взаимодействий конструируются путем явного соединения функций и/или событий DOM так, что выполнение одной функции автоматически влечет за собой вызов другой. Например, вы можете захотеть, чтобы при каждом изменении какоголибо объекта посредством метода «записи» автоматически производилось изменение в визуальном интерфейсе приложения. Или чтобы каждое изменение одного объекта автоматически вызывало обновление свойств другого объекта. Варианты могут быть самые разные.

В схему прямого взаимодействия вовлечены два основных метода – dojo.connect и dojo.disconnect. Проще говоря, метод dojo.connect используется для объединения в цепь последовательности событий. При каждом обращении к методу dojo.connect возвращается дескриптор, который необходимо сохранять и явно передавать методу dojo.disconnect, когда требуется разорвать связь. Обычно при выгрузке страницы все соединения разрываются автоматически, однако ручное управление дескрипторами может потребоваться, чтобы предотвратить утечки памяти в долгоживущих приложениях, которые устанавливают множество временных соединений. (Это особенно справедливо в отношении IE.)

Установка и разрыв соединения выполняются достаточно просто.


Ниже приводятся сигнатуры используемых функций:
/* Устанавливает соединение */
dojo.connect(/*Object|null*/ obj,
/*String*/ event,
/*Object|null*/ context,
/*String|Function*/ method) // Возвращает дескриптор Handle
/* Разрывает соединение */
dojo.disconnect(/*Handle*/handle);

Давайте рассмотрим пример, иллюстрирующий своего рода проблему, которую можно решить с помощью функции dojo.connect:
function Foo() {
this.greet = function() { console.log("Hi, I'm Foo"); }
}
function Bar() {
this.greet = function() { console.log("Hi, I'm Bar"); }
}
foo = new Foo;
bar = new Bar;
foo.greet();
//объект bar должен отвечать на приветствие объекта foo
//всегда, когда объект bar существует.

Оказывается, что решить эту маленькую проблему можно всего одной строкой программного кода. Измените предыдущий листинг, как показано ниже, и проверьте его в Firebug:
function Foo() {
this.greet = function() { console.log("Hi, I'm foo"); }
}

function Bar() {
this.greet = function() { console.log("Hi, I'm bar"); }
}
foo = new Foo;
bar = new Bar;
//При каждом вызове foo.greet автоматически будет вызываться bar.greet ...
var handle = dojo.connect(foo, "greet", bar, "greet"); //устанавливается
//соединение
foo.greet(); //теперь объект bar автоматически ответит на приветствие!

Вы написали всего одну строчку, а получили такой приятный результат – неплохо, не правда ли? Обратите внимание, что второй и четвертый параметры, переданные функции dojo.connect, – строковые литералы для соответствующих им контекстов и что функция возвращает дескриптор, который позднее позволит разорвать это соединение.


Вообще говоря, всегда наступает некоторый момент, когда следует разорвать соединение – либо приложение достигает некоторого функционального состояния, либо вы выполняете некоторые завершающие действия, например при уничтожении некоторого объекта или при закрытии страницы, примерно так, как показано ниже:
var handle = dojo.connect(foo, "greet", bar, "greet");
foo.greet();
dojo.disconnect(handle);
foo.greet(); //на сей раз ответного приветствия не последует

Кроме того что dojo.connect позволяет добиться такого значительного эффекта такими малыми усилиями, обратите внимание, насколько опрятным и понятным остался программный код. Никаких шаблонных заготовок, никакой путаницы, никаких накрученных решений и никакого кошмара для того, кто будет это сопровождать. Запуск методов в ответ на события, происходящие в странице, – действительно очень удобная возможность, но помимо этого рано или поздно появится необходимость передавать таким методам какие-нибудь аргументы. Оказывается, функция connect обладает возможностью передавать аргументы из контекста одной функции в контекст другой функции. Ниже приводится пример, как это делается:
function Foo() {
this.greet = function(greeting) { console.log("Hi, I'm Foo.",greeting); };
}
function Bar() {
this.greet = function(greeting) { console.log("Hi, I'm Bar.",greeting); };
}
foo = new Foo;
bar = new Bar;
var handle= dojo.connect(foo, "greet", bar, "greet");
foo.greet("Nice to meet you");

Вы наверняка можете оценить, насколько удобно, когда передача аргументов происходит автоматически, и это особенно верно для функций, связанных с событиями DOM, например щелчок мышью, потому что такая возможность обеспечивает для функции моментальный доступ ко всем важным сведениям о событии, таким как целевой элемент, координаты указателя мыши и т.


д. Давайте рассмотрим еще один пример:
//Обратите внимание, что третий аргумент опущен, так как обработчик -
//это анонимная функция. Если в третьем аргументе передать значение null,
//мы получим тот же самый эффект.
dojo.connect(
dojo.byId("foo"), //Некоторый элемент DOM
"onmouseover",
function(evt) {
console.log(evt);
});

Если создать пробную страницу, установить в ней соединение и наблюдать за происходящим в консоли Firebug, можно заметить, что функцииобработчику объект события, содержащий практически все сведения, какие только может потребоваться знать о только что произошедшем событии доступен целиком.

Возникает резонный вопрос: «Если настолько просто определять обработчики событий DOM, зачем тогда заниматься изучением другой библиотечной функции?». Да, возможно, не требуется быть нейрохирургом, чтобы собрать вместе несколько простых обработчиков событий, но как быть, когда имеется сложное приложение, основанное на обработке большого числа сложных событий с учетом предпочтений пользователя, на обработке нестандартных событий или обладающее иным поведением, управляемым событиями? Несомненно, всю необходимую работу можно выполнить вручную, но сможете ли вы устанавливать и разрывать соединение однострочными командами, с единым непротиворечивым интерфейсом, уже написанными и всесторонне проверенными?

Наконец, обратите внимание: хотя в приведенных примерах связывались между собой только пара событий, вам ничто не мешает связать воедино произвольное число обычных функций, методов объектов и событий DOM для их последовательного вызова..



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Dojo на эту тему:
Использование замыканий с функцией dojo.connect
Нормализация событий и клавиатуры
Организация взаимодействий по подписке
Распространение событий