如何设置活动的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
修改
我想写这样的东西,我的班级将是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
答案 0 :(得分:12)
好的 - 我只是有一个脑波,所以这里的另一个答案对你来说非常顽皮,可能只是工作。 (为我工作;)
您可以尝试:{/ p>而不是const object1 = {};
Object.defineProperty(object1, 'property1', {
value: [{
value: 42,
writable: false
}]
});
console.log(object1.property1[0].value);
console.log(object1.property1[0].writable);
event.target = myObj
我可能在这里错了,但我认为新的Object.defineProperty(event, 'target', {writable: false, value: myObj});
属性会隐藏原始属性。它与浏览器内部事件调度的工作方式不同,浏览器事件处理代码几乎肯定会忽略它,但它可能足以欺骗依赖target
的javascript代码。
另外,请注意在不同的浏览器中测试它,因为某些浏览器可能会将Event.target
定义为不可配置的属性。
答案 1 :(得分:4)
关于您的修改, 显着 会更改问题。现在的答案是:不要使用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);
&#13;
<div id="target"></div>
&#13;
答案 2 :(得分: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()
如果你把它变成一个空回调(另一个简单的修复)就不会简单地返回,显然它不允许将选项交给它。 (但决定你是否真的需要这个功能)