首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript dispatchEvent非调度

JavaScript dispatchEvent非调度
EN

Stack Overflow用户
提问于 2019-01-11 01:08:58
回答 3查看 3.5K关注 0票数 0

我在让dispatchEvent工作上有个问题。我正试图消除对jQuery的依赖,并且一直在对本机API做一些小小的扩展,但是我无法使用dispatchEvent使我的trigger版本正常工作。

在控制台记录所有内容之后,我知道eventType正在传递,event对象正在创建,this引用了正确的目标元素。这是我的密码,我很感谢你的帮助。

代码语言:javascript
复制
if (!EventTarget.prototype.trigger) {
    function triggerFunction(
        eventType) {
        const event = new CustomEvent(eventType, {
            bubbles: true,
            cancelable: true
        });

        this.dispatchEvent(event);
    }

    EventTarget.prototype.trigger = triggerFunction;
}

编辑

这是剩下的代码。其实没什么可做的,因为我主要是集中精力构建我的扩展。

代码语言:javascript
复制
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:

代码语言:javascript
复制
<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版本中,这个功能非常好。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-01-11 05:42:04

问题是,浏览器不仅要查看事件的type属性,还需要从正确的事件子类继承它。

在这种情况下,他们想要的事件的一个子类是MouseEvent,所以您必须执行dispatchEvent(new MouseEvent('click'))而不是dispatchEvent(new CustomEvent('click'));

(MCVE借用@CertainPerformance的答案)。

代码语言:javascript
复制
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
});
代码语言:javascript
复制
<div>
  <button type="button">{UPLOAD}</button>
  <input type="file">
</div>

但是,如果您想要的是真正触发单击事件,那么一定要使用HTMLElement.click()

不需要任何库,也不需要修改EventTarget的原型,这是一个非常糟糕的想法。

代码语言:javascript
复制
const button = document.querySelector('button');
const input = document.querySelector('input');
button.addEventListener('click', () => {
  input.click(); // Works
});
代码语言:javascript
复制
<div>
  <button type="button">{UPLOAD}</button>
  <input type="file">
</div>

票数 1
EN

Stack Overflow用户

发布于 2019-01-11 04:36:26

这里有一个更小的MCVE:

代码语言:javascript
复制
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
});
代码语言:javascript
复制
<div>
  <button type="button">{UPLOAD}</button>
  <input type="file">
</div>

问题是分派事件不会触发打开输入对话框的(浏览器内置)函数。分派的事件确实会触发其他正常侦听器。

我怀疑,在不调用内置click函数的情况下,是否有办法做到这一点,该函数调用浏览器的本机代码,该代码允许出现对话框。一种可能是检查eventType是否为clickEventTarget是否为HTMLElement。这似乎是在回避这个问题,但我认为当目标需要为对话框调用浏览器的本机代码时,没有另一种方法。

代码语言:javascript
复制
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
});
代码语言:javascript
复制
<div>
  <button type="button">{UPLOAD}</button>
  <input type="file">
</div>

在调用任何需要运行本机代码的方法时,都需要类似的模式(如console.logXMLHttpRequest (如果fetch不可用,则为setTimeout )--有些东西无法使用您自己的Javascript进行模拟,并且需要调用浏览器的一些本机代码)。

还请注意,看起来您只是在向HTML元素中添加自定义方法,在这种情况下,将trigger分配给HTMLElement.prototype而不是EventTarget.prototype可能更好

代码语言:javascript
复制
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
});
代码语言:javascript
复制
<div>
  <button type="button">{UPLOAD}</button>
  <input type="file">
</div>

票数 0
EN

Stack Overflow用户

发布于 2019-01-11 15:17:27

多亏了@Kaiido,我现在又让它起作用了。我添加了一个getEvent函数来打开eventType并返回正确的事件对象。更新后的代码如下:

代码语言:javascript
复制
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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54139084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档