如何正确触发JavaScript自定义事件

时间:2015-06-25 10:36:14

标签: javascript addeventlistener dispatchevent custom-events

我很难理解自定义事件类型如何链接到特定的用户操作/触发器。所有文档似乎都在没有任何用户交互的情况下发送事件。

在下面的示例中,我希望在用户将元素悬停3秒后调度该事件。

var img = document.createElement('img');img.src = 'http://placehold.it/100x100';
document.body.appendChild(img)
var event = new CustomEvent("hoveredforthreeseconds");

img.addEventListener('hoveredforthreeseconds', function(e) { console.log(e.type)}, true);


var thetrigger = function (element, event) {
    var timeout = null;
    element.addEventListener('mouseover',function() {
        timeout = setTimeout(element.dispatchEvent(event), 3000);
    },true);
    element.addEventListener('mouseout', function() {
        clearTimeout(timeout);
    },true);
};

我有一个触发器,但没有逻辑方法将它连接到事件。

我正在考虑创建一个名为CustomEventTrigger的对象,该对象本质上是CustomEvent但是有一个触发器的第三个参数,还创建了一个名为addCustomEventListener的方法,其作用与addEventListener相同。 {1}}但是在初始化时,它会将目标Element传递给自定义事件触发器,然后在指示时调度该事件。

2 个答案:

答案 0 :(得分:1)

自定义事件必须通过dispatchEvent以编程方式触发,它们不会被DOM触发。您始终需要在代码中明确地调用它们,例如响应用户生成的事件(例如onmouseover)或更改状态(例如onload

您非常接近工作实施,但是您立即在dispatchEvent中调用setTimeout。如果将其保存到闭包中(如下所示),则可以在dispatchEvent完成超时后传递元素时调用setTimeout

将变量声明在文件顶部也是一种好习惯,以避免可能的范围问题。

var img = document.createElement('img'), timeout, event, thetrigger;

img.src = 'http://placehold.it/100x100';
document.body.appendChild(img);

img.addEventListener("hoveredForThreeSeconds", afterHover, false);

thetrigger = function (element, event) {
    timeout = null;
    element.addEventListener('mouseover',function() {
      timeout = setTimeout(function(){ element.dispatchEvent(event) }, 3000);
    },true);
    element.addEventListener('mouseout', function() {
        clearTimeout(timeout);
    },true);
};

function afterHover(e) {
    console.log("Event is called: " + e.type);
}

event = new CustomEvent("hoveredForThreeSeconds");

thetrigger(img, event);

答案 1 :(得分:1)

我创建了一个名为addCustomEventListener的方法,它与addEventListener的工作方式相同,但是在初始化时将目标元素传递给自定义事件触发器,该触发器在事件发生时调度该事件,因此在这种情况下它仅在超时达到3秒时发送。



var img = document.getElementById('img');

window.mouseover3000 = new CustomEvent('mouseover3000', {
  detail: {
    trigger: function(element, type) {
      timeout = null;
      element.addEventListener('mouseover', function() {
        timeout = setTimeout(function() {
          element.dispatchEvent(window[type])
        }, 3000);
      }, false);
      element.addEventListener('mouseout', function() {
        clearTimeout(timeout);
      }, false)
    }
  }
});

window.tripleclick = new CustomEvent('tripleclick', {
  detail: {
    trigger: function(element, type) {
      element.addEventListener('click', function(e) {
        if(e.detail ===3){
          element.dispatchEvent(window[type])
        }    
      }, false);
    }
  }
});
EventTarget.prototype.addCustomEventListener = function(type, listener, useCapture, wantsUntrusted) {

  this.addEventListener(type, listener, useCapture, wantsUntrusted);
  window[type].detail.trigger(this, type);
}

var eventTypeImage = function(e) {
  this.src = "http://placehold.it/200x200?text=" + e.type;
}

img.addEventListener('mouseout', eventTypeImage, false);
img.addEventListener('mouseover', eventTypeImage, false);
img.addCustomEventListener('mouseover3000', eventTypeImage, false);
img.addCustomEventListener('tripleclick', eventTypeImage, false);

<img id="img" src="http://placehold.it/200x200?text=No+hover" ;/>
&#13;
&#13;
&#13;

我认为这对其他人有用,所以请随时改进。