代码之家  ›  专栏  ›  技术社区  ›  Gup3rSuR4c

javascript DispatchEvent未调度

  •  0
  • Gup3rSuR4c  · 技术社区  · 6 年前

    我有个问题 dispatchEvent 去工作。我正在尝试消除对jquery的依赖,并且一直在对本机API进行自己的小扩展,但是我无法获得我的版本 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>
    

    基本上,当按下按钮时,我想触发input:file的click事件,这样我就可以用css将其隐藏起来。在我的jquery版本中,这工作得很好。

    3 回复  |  直到 6 年前
        1
  •  1
  •   Kaiido NickSlash    6 年前

    问题是,浏览器不仅可以看到 type 属性,它们还要求它从正确的事件子类继承。

    在这种情况下,他们想要的事件的一个子类是mouseEvent,所以不是 dispatchEvent(new CustomEvent('click')); 你得这么做 dispatchEvent(new MouseEvent('click')) .

    (mcve借用了@certainperformance answer)。

    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() .

    不需要任何lib,也不需要修改EventTarget的原型,这是一个非常糟糕的主意。

    const button = document.querySelector('button');
    const input = document.querySelector('input');
    button.addEventListener('click', () => {
      input.click(); // Works
    });
    <DIV & GT;
    <button type=“button”>上传</button>
    <input type=“file”>
    &L/DIV & GT;
        2
  •  0
  •   CertainPerformance    6 年前

    这里有一个更简单的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 点击 如果 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 & GT;
    <button type=“button”>上传</button>
    <input type=“file”>
    &L/DIV & GT;

    调用任何需要运行本机代码的方法(如 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 & GT;
    <button type=“button”>上传</button>
    <input type=“file”>
    &L/DIV & GT;
        3
  •  0
  •   Gup3rSuR4c    6 年前

    多亏了@kaido,我现在又开始工作了。我添加了一个 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;
    }