我在让dispatchEvent工作上有个问题。我正试图消除对jQuery的依赖,并且一直在对本机API做一些小小的扩展,但是我无法使用dispatchEvent使我的trigger版本正常工作。
在控制台记录所有内容之后,我知道eventType正在传递,event对象正在创建,this引用了正确的目标元素。这是我的密码,我很感谢你的帮助。
if (!EventTarget.prototype.trigger) {
function triggerFunction(
eventType) {
const event = new CustomEvent(eventType, {
bubbles: true,
cancelable: true
});
this.dispatchEvent(event);
}
EventTarget.prototype.trigger = triggerFunction;
}编辑
这是剩下的代码。其实没什么可做的,因为我主要是集中精力构建我的扩展。
if (!EventTarget.prototype.on) {
function onFunction(
eventType,
targetElement,
listener) {
if (targetElement) {
this.addEventListener(eventType, function (
event) {
const target = event.target;
if (target
&& target.nodeName !== targetElement) {
return;
}
listener.call(target, event);
}, false);
return this;
}
this.addEventListener(eventType, listener, false);
return this;
}
EventTarget.prototype.on = onFunction;
}
const _pointerTap = "click";
const photosFunction = () => {
const $buttonPhotosUpload = document.getElementById("button-photos-upload"),
$fieldPhotosUpload = document.getElementById("field-photos-upload");
const onButtonPhotosUploadTap = () => $fieldPhotosUpload.trigger(_pointerTap);
$buttonPhotosUpload.on(_pointerTap, null, onButtonPhotosUploadTap);
};
document.getElementById("photos") && photosFunction();以及HTML:
<div id="photos">
<div>
<button type="button" id="button-photos-upload">{UPLOAD}</button>
<input type="file" id="field-photos-upload" accept="image/*" multiple />
</div>
</div>基本上,当按下按钮时,我希望触发输入:file的click事件,这样我就可以用CSS直观地隐藏它。在我的jQuery版本中,这个功能非常好。
发布于 2019-01-11 05:42:04
问题是,浏览器不仅要查看事件的type属性,还需要从正确的事件子类继承它。
在这种情况下,他们想要的事件的一个子类是MouseEvent,所以您必须执行dispatchEvent(new MouseEvent('click'))而不是dispatchEvent(new CustomEvent('click'));。
(MCVE借用@CertainPerformance的答案)。
function triggerMouseFunction(eventType) {
// here event must be MouseEvent for it to work on <input>
const event = new MouseEvent(eventType, {
bubbles: true,
cancelable: true
});
this.dispatchEvent(event);
}
if (!EventTarget.prototype.triggerMouse) {
EventTarget.prototype.triggerMouse = triggerMouseFunction;
}
const button = document.querySelector('button');
const input = document.querySelector('input');
button.addEventListener('click', () => {
input.triggerMouse('click'); // Works
});<div>
<button type="button">{UPLOAD}</button>
<input type="file">
</div>
但是,如果您想要的是真正触发单击事件,那么一定要使用HTMLElement.click()。
不需要任何库,也不需要修改EventTarget的原型,这是一个非常糟糕的想法。
const button = document.querySelector('button');
const input = document.querySelector('input');
button.addEventListener('click', () => {
input.click(); // Works
});<div>
<button type="button">{UPLOAD}</button>
<input type="file">
</div>
发布于 2019-01-11 04:36:26
这里有一个更小的MCVE:
function triggerFunction(eventType) {
const event = new CustomEvent(eventType, {
bubbles: true,
cancelable: true
});
this.dispatchEvent(event);
}
if (!EventTarget.prototype.trigger) {
EventTarget.prototype.trigger = triggerFunction;
}
const button = document.querySelector('button');
const input = document.querySelector('input');
button.addEventListener('click', () => {
// input.click(); // Works
// input.trigger('click'); // Doesn't work
});<div>
<button type="button">{UPLOAD}</button>
<input type="file">
</div>
问题是分派事件不会触发打开输入对话框的(浏览器内置)函数。分派的事件确实会触发其他正常侦听器。
我怀疑,在不调用内置click函数的情况下,是否有办法做到这一点,该函数调用浏览器的本机代码,该代码允许出现对话框。一种可能是检查eventType是否为click,EventTarget是否为HTMLElement。这似乎是在回避这个问题,但我认为当目标需要为对话框调用浏览器的本机代码时,没有另一种方法。
function triggerFunction(eventType) {
if (this instanceof HTMLInputElement && eventType === 'click') {
return HTMLElement.prototype.click.call(this);
}
const event = new CustomEvent(eventType, {
bubbles: true,
cancelable: true
});
this.dispatchEvent(event);
}
if (!EventTarget.prototype.trigger) {
EventTarget.prototype.trigger = triggerFunction;
}
const button = document.querySelector('button');
const input = document.querySelector('input');
button.addEventListener('click', () => {
input.trigger('click'); // Works
});<div>
<button type="button">{UPLOAD}</button>
<input type="file">
</div>
在调用任何需要运行本机代码的方法时,都需要类似的模式(如console.log或XMLHttpRequest (如果fetch不可用,则为setTimeout )--有些东西无法使用您自己的Javascript进行模拟,并且需要调用浏览器的一些本机代码)。
还请注意,看起来您只是在向HTML元素中添加自定义方法,在这种情况下,将trigger分配给HTMLElement.prototype而不是EventTarget.prototype可能更好
function triggerFunction(eventType) {
if (this instanceof HTMLInputElement && eventType === 'click') {
return HTMLElement.prototype.click.call(this);
}
const event = new CustomEvent(eventType, {
bubbles: true,
cancelable: true
});
this.dispatchEvent(event);
}
if (!HTMLElement.prototype.trigger) {
HTMLElement.prototype.trigger = triggerFunction;
}
const button = document.querySelector('button');
const input = document.querySelector('input');
button.addEventListener('click', () => {
input.trigger('click'); // Works
});<div>
<button type="button">{UPLOAD}</button>
<input type="file">
</div>
发布于 2019-01-11 15:17:27
多亏了@Kaiido,我现在又让它起作用了。我添加了一个getEvent函数来打开eventType并返回正确的事件对象。更新后的代码如下:
function getEvent(
eventType): Event {
switch (eventType) {
case "keydown":
case "keypress":
case "keyup":
return new KeyboardEvent(eventType);
case "click":
case "dblclick":
case "mouseup":
case "mousedown":
return new MouseEvent(eventType);
default:
return new CustomEvent(eventType);
}
}
function triggerFunction(
eventType) {
const event = getEvent(eventType);
event.bubbles = true;
event.cancelable = true;
this.dispatchEvent(event);
}
if (!EventTarget.prototype.trigger) {
EventTarget.prototype.trigger = triggerFunction;
}https://stackoverflow.com/questions/54139084
复制相似问题