2014-02-05 3 views
4

Пытаюсь (возможно, напрасно), чтобы придумать способ использовать шаблон публикации-подписки, а а) использованием нет библиотек и б) минимизируя шаблонный код в модулях, которые используют его. До сих пор лучшее, что я придумал это:Есть ли способ реализовать EventTarget с простым JS?

var handle = document.createElement(); 
var unsubscribe = AwesomeModule.subscribe(handle); 

handle.addEventListener('awesome', function() { 
    console.log('awesome'); 
}); 

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

Я попытался следующие, и он не работает слишком хорошо:

var handle = Object.create(EventTarget); 
var unsubscribe = AwesomeModule.subscribe(handle); 

handle.addEventListener('awesome', function(){ 
    console.log('awesome') 
}); 

я TypeError: Object [object Object] has no method 'addEventListener'. Интересно, что в цепочке прототипов, похоже, нет, хотя дескриптор имеет EventTarget в качестве своего прототипа.

Почему это не работает? Есть ли способ реализации EventTarget с чистым JS? Можно ли это сделать в одной строке кода, которая не будет ужасать пользователей AwesomeModule?

EDIT: Я не знаю, почему это не произошло со мной прошлой ночью, но я полагаю, что EventTarget является интерфейсом, что он не имеет реализованного кода. Что вводит в заблуждение, так это то, что в консоли отладчика Chrome Object.create(EventTarget) создает объект, который появляется, чтобы addEventListener in был прототипом цепочки. Возможно, его ложь. Может ли кто-нибудь объяснить это поведение? Может ли кто-нибудь объяснить, почему W3 решил не делать EventTarget конкретным «классом»?

+0

addEventListener не поддерживается в Internet Explorer 6, 7, и я думаю, что вам нужно использовать attachEvent. Для функции библиотеки, которая поддерживает оба варианта, вы можете использовать один из них: // --- http://ejohn.org/projects/flexible-javascript-events/ – jeff

+1

@MattBall Его основная часть браузера JS: https: // developer.mozilla.org/en-US/docs/Web/API/EventTarget. – acbabis

+1

@jeff Я сейчас не заинтересован в совместимости с браузером. У меня проблема с Chrome. – acbabis

ответ

2

Похоже, что ответ на мой первоначальный вопрос - «да». Поскольку JavaScript не имеет такой модели наследования, как Java, которая выполняет проверки времени компиляции для юридической реализации, я полагаю, что любой объект может реализовать интерфейс, просто используя методы с тем же именем. Однако сделать это будет создание библиотеки, поскольку код addEventListener не реализован в EventTarget (ранее я предполагал, что это было). Поскольку, похоже, нет кросс-браузерного способа получения ванильного EventTarget, я, вероятно, буду использовать window.addEventListener в сочетании с настраиваемыми событиями.

1

Источник находится здесь: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/trace-viewer/src/base/event_target.js&sq=package:chromium&type=cs&l=18

Если вы не можете изменить его, вы всегда можете повторить его.

+0

Это интересно. Означает ли это, что у вас может быть «конкретный» ванильный EventTarget в Chromium? – acbabis

+0

Новая ссылка: https://cs.chromium.org/chromium/src/ui/webui/resources/js/cr/event_target.js?q=event_target&dr –

1

Вот простой набор подпрограмм, который хорошо работает. с a small polyfill for IE9 and 10, поддержка приличная.

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

var on = addEventListener.bind(window), 
off = removeEventListener.bind(window), 
emit = function(name, val) { 
    dispatchEvent(new CustomEvent(name, { 
     detail: val 
    })); 
}; 



// demo: 
on("test", function(e){ alert(e.detail);}); 
emit("test", "Number is " + Math.random()); 

я не думаю, что он может получить гораздо проще (~ 180 символов) без ущерба для совместимости скорости или библиотеки.

+0

Это выглядит очень удобно, но по-прежнему использует элементы DOM. Я могу использовать что-то вроде этого, но я не уверен, что считаю его ответом на мои вопросы. – acbabis

+0

, где он использует любые элементы DOM? – dandavis

+0

Вы используете окно в качестве глобального диспетчера событий. Как я уже сказал, ваш способ полезен, потому что он скрывает синонимы DOM от пользователя модуля, но я действительно надеялся на способ привязки событий к объекту, отличному от DOM. – acbabis

Смежные вопросы