2016-05-26 2 views
2

Как установить EventTarget события.Как установить EventTarget события

var myObj = {foo: 'bar'}; 
var event = new Event('eventName'); 
event.target = myObj; 

приведет к следующей ошибке:

Uncaught TypeError: Cannot set property target of #<Event> which has only a getter 

Edit:

Я хочу написать что-то вроде этого, где мой класс будет target:

class MyClass { 

    constructor() { 
    this.listeners = {}; 
    } 

    addEventListener(type, callback) { 
    if (!(type in this.listeners)) { 
     this.listeners[type] = []; 
    } 
    this.listeners[type].push(callback); 
    } 

    removeEventListener() { 
    if (!(type in this.listeners)) { 
     return; 
    } 
    var stack = this.listeners[type]; 
    for (var i = 0, l = stack.length; i < l; i++) { 
     if (stack[i] === callback) { 
     stack.splice(i, 1); 
     return this.removeEventListener(type, callback); 
     } 
    } 
    } 

    dispatchEvent(event) { 
    if (!(event.type in this.listeners)) { 
     return; 
    } 
    var stack = this.listeners[event.type]; 
    event.target = this; 
    for (var i = 0, l = stack.length; i < l; i++) { 
     stack[i].call(this, event); 
    } 
    } 

} 

let myInstance = new MyClass(); 
let event = new Event('eventName'); 
myInstance.dispatchEvent(); 

Дополнительная информация: https://developer.mozilla.org/en/docs/Web/API/EventTarget

+1

Возможно, я ошибаюсь, но «EventTarget» обычно автоматически устанавливается браузером как элемент, на котором было запущено/запущено событие. Что вы пытаетесь сделать? Он * чувствует * из ограниченной информации в вашем вопросе, что вы должны использовать 'EventTarget.addEventListener()', но я очень, очень не уверен в ваших намерениях до сих пор. –

ответ

2

Что касается вашего редактирования, он заметно меняет вопрос. Теперь ответ: Не используйте CustomEvent, вы пытаетесь использовать его для чего-то другого, кроме его намеченной цели. Просто используйте свой собственный объект, так как вы никогда не отправляете событие в элемент DOM.


Она устанавливается автоматически при отправки событие:

targetElement.dispatchEvent(event); 

Если вы хотите, чтобы включить пользовательские кроме элемента с событием данные, просто добавьте его в качестве свойства:

event.data = myObj; 

Пример:

"use strict"; 
 
var div = document.getElementById("target"); 
 

 
div.addEventListener(
 
    "eventName", 
 
    function(e) { 
 
    console.log("e.target:", e.target); 
 
    console.log("e.data:", e.data); 
 
    }, 
 
    false 
 
); 
 

 
var myObj = {foo: "bar"}; 
 
var event = new Event("eventName"); 
 
event.data = myObj; 
 
div.dispatchEvent(event);
<div id="target"></div>

+0

Я не хочу, чтобы DOMEEM был EventTarget. Вместо этого он должен быть объектом моего выбора. – HaNdTriX

+0

@HaNdTriX: Ваше редактирование очень сильно изменяет вопрос, почти достаточно, чтобы его нужно было отбросить назад. (По сути, изменение вопроса после того, как у него есть ответы, не разрешено на SO. Я думаю, что это * чуть-чуть проскальзывает.) Я отредактировал ответ, чтобы ответить на новый вопрос. –

+0

Я никогда не упоминал элементы DOM. Я пытался уменьшить свою проблему до необходимой части. В Javascript есть много примеров, где Событие имеет цель, которая не является элементом DOM. (например: Уведомления) Извините, что не понимаете этого. – HaNdTriX

1

Это 1 год, 9 месяцев на от вашего первоначального вопроса, и я хочу сделать именно это с точно таким же кодом, с точно таким же места. Я точно знаю, почему вы хотите это сделать, потому что EventTarget не является конструктивным объектом во всех браузерах. И, похоже, нет, нет реального решения вашей проблемы.

Если у кого-то еще есть эта проблема и наткнулся на эту страницу, решение не должно полагаться на Event.target. Вы можете создать пользовательское событие и направить его, как это:

var myeventtarget = new MyClass(); 

var ev = new CustomEvent('myevent', { 
    detail: { 
     target: myeventtarget 
    }}); 

myeventtarget.dispatchEvent(ev); 

Затем в обработчике события, цель может быть доступна с:

var event_handler = function(ev) { 
    var target = ev.detail.target; 
    alert(target); 
} 

Это действительно некрасиво синтаксис, но это выглядит только «правильный» способ, которым это может быть достигнуто прямо сейчас. Теперь, если игнорировать старые браузеры, я знаю, что в новом Firefox и Chrome браузеров, вы можете реализовать MyClass так:

class MyClass extends EventTarget { 
    constructor() { 
     super() 
    } 
} 

Я не проверял целевое событие, установлен ли когда отправляются на объекте тип MyClass, учитывая приведенное выше определение, но если нет, возможно, стоит предположить его как изменение стандарта DOM Living Standard, поскольку оно имеет смысл.(спецификация в настоящее время не показывает, что она должна работать)

Наконец, могу ли я предостеречь вас от использования кода javascript EventTarget, который вы используете, не проверяя, что он работает правильно. Я обнаружил, что он ломается, когда вы передаете его объекту EventListener. Он также добавляет повторяющееся событие, если вы дважды передаете одно и то же событие в addEventListener(), в то время как в DOM Living Standard четко указано, что он не должен этого делать. К счастью, очень легко исправить эти проблемы. Вам нужно изменить stack[i].call(this, event); к:

if (stack[i].handleEvent) stack[i].handleEvent(event); 
     else stack[i].call(this, event); 

И добавить следующее:

var stack = this.listeners[type]; 
for (var i = 0, l = stack.length; i < l; i++) { 
    if (stack[i] === callback){ 
     return; 
    } 
} 

перед тем this.listeners[type].push(callback);

Другие проблемы, которые addEventListener() не просто вернуться, если вы передадите ему нулевой обратный вызов (еще одно простое исправление), и, очевидно, это не позволяет передавать им параметры. (но решите, действительно ли вам нужна эта функция).

0

Хорошо. У меня просто была мозговая волна, и вот еще один ответ для вас, это очень непослушный и может просто работать. (Работал для меня;)

Вместо того чтобы делать event.target = myObj, вы можете попробовать:

Object.defineProperty(event, 'target', {writable: false, value: myObj}); 

Я могу ошибаться, но я думаю, что происходит в том, что новый target свойство скрывает оригинал. Он не работает так же, как диспетчеризация внутренних событий браузера, и код обработки событий браузера почти наверняка игнорирует его, но этого может быть достаточно, чтобы обмануть код javascript, который полагается на Event.target.

Кроме того, будьте осторожны, чтобы протестировать его в разных браузерах, поскольку некоторые браузеры могут определять Event.target как неконфигурируемое свойство.

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