Internet Explorer 9、10和11事件构造函数不起作用


129

我正在创建一个事件,因此请使用DOM Event构造函数:

new Event('change');

在现代浏览器中,此方法工作正常,但是在Internet Explorer 9、10和11中,它失败并显示:

Object doesn't support this action

如何修复Internet Explorer(最好通过polyfill)?如果不能,是否可以使用替代方法?


55
“如何修复Internet Explorer?” xD
contactmatt

Answers:


176

MDN的CustomEvent构造函数有一个IE polyfill。将CustomEvent添加到IE并使用它可以。

(function () {
  if ( typeof window.CustomEvent === "function" ) return false; //If not IE

  function CustomEvent ( event, params ) {
    params = params || { bubbles: false, cancelable: false, detail: undefined };
    var evt = document.createEvent( 'CustomEvent' );
    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
    return evt;
   }

  CustomEvent.prototype = window.Event.prototype;

  window.CustomEvent = CustomEvent;
})();

14
先生,您救了我的命。完全替代是否安全?我的意思是,window.Event= CustomEvent在最后一行做。
tfrascaroli

7
在IE11中,似乎设置window.Event = CustomEvent是安全的。
Corey Alix

10
对于任何感兴趣的人,似乎都可以通过检查typeof(Event)来检测您是否在IE中(对于这种情况),对于所有除外的IE,它都是“功能”,而IE是“对象”。然后,您可以使用上述方法安全地填充Event构造函数。
Euan Smith

我只是在研究类似的解决方法StorageEventtypeof(StorageEvent)但在MS Edge中不起作用。这工作:try { new StorageEvent(); } catch (e) { /* polyfill */ }
kamituel

1
如果使用的第三方库使用IE定义的CustomEvent构造函数,则替换window.CustomEvent可能并不安全。
森·雅各布

55

我认为解决您的问题并处理跨浏览器事件创建的最佳解决方案是:

function createNewEvent(eventName) {
    var event;
    if (typeof(Event) === 'function') {
        event = new Event(eventName);
    } else {
        event = document.createEvent('Event');
        event.initEvent(eventName, true, true);
    }
    return event;
}

3
有用!我只是认为应该return event这样做,所以我可以将其传递给dispatchEvent()
Noumenon

initEvent已过时已过时的,您至少需要使用现代方式,而作为后备设备,请使用已过时的方式。
vsync

2
@vsync它可能已被弃用,但您链接的文档说“而不是使用特定的事件构造函数,如Event()”,这正是它试图进行polyfill的原因,因此实际上没有选择。
重新收藏了

1
CustomEvent允许通过detail选项传递自定义数据,Event但不允许。我错了吗?
pttsky '18

1
根据我的经验,IE9、10或11不支持CustomEvent。唯一的好答案似乎是被接受。
UndyingJellyfish

5

该软件包具有神奇的作用:

https://www.npmjs.com/package/custom-event-polyfill

包括软件包并按以下方式调度事件:

window.dispatchEvent(new window.CustomEvent('some-event'))

95个依赖项?
Damien Roche

4
@DamienRoche难道您会误读“ Dependents”为“ Dependencies”吗?因为该包实际上具有0个依赖项,并且(截至撰写本文时)具有102个依赖项(即,依赖于它的包)。102个依赖包可能在7月回到95个。
流感

2
我干得好!:P
Damien Roche

3

如果您只是尝试分发一个简单的事件(例如HTML切换事件),则该事件在Internet Explorer 11和其他浏览器中均可使用:

let toggle_event = null;
try {
    toggle_event = new Event("toggle");
}
catch (error) {
    toggle_event = document.createEvent("Event");
    let doesnt_bubble = false;
    let isnt_cancelable = false;
    toggle_event.initEvent("toggle", doesnt_bubble, isnt_cancelable);
}
// disclosure_control is a details element.
disclosure_control.dispatchEvent(toggle_event);

5
无法看到您为什么混用es6 let(而不使用var)与应该在旧IE上运行的代码..这可能会使初学者复制并粘贴此内容感到困惑
vsync

1
@vsync 耸耸肩确实提到了版本号。我的个人网站去年仅针对IE11,因此我从来没有想过要检查旧版本的支持。(到目前为止,我提供的是不含样式表或脚本的IE11纯HTML。人们需要继续前进。)无论如何,截至2017年4月,Microsoft仍支持的唯一Internet Explorer版本是11。争论的焦点。我不会鼓励任何人通过定位不受支持的浏览器来使用它。网络可能是危险的地方。
Patrick Dark

3
这根本不关乎它,也不关乎改变世界或任何事情。例如,问题的标题特别要求IE 9,并且可能是一个找到该线程的寻求答案的人正在为遗留银行系统或某些其他系统开发应用程序,这些系统无法控制他们的计算机,并且对企业客户有义务使用旧的IE。这与Microsoft支持无关
。– vsync


2

custom-eventNPM包精美的工作对我来说

https://www.npmjs.com/package/custom-event

var CustomEvent = require('custom-event');

// add an appropriate event listener
target.addEventListener('cat', function(e) { process(e.detail) });

// create and dispatch the event
var event = new CustomEvent('cat', {
  detail: {
    hazcheeseburger: true
  }
});
target.dispatchEvent(event);

这是一个很好的答案,但是已经提到了另一个NPM软件包作为答案。
mikemaccana

2
为用户提供多种选择有什么问题?
Liran H

一个更通用的软件包是npmjs.com/package/events-polyfill
Markus Jarderot,

1

我个人使用包装函数来处理手动创建的事件。下面的代码将在所有Event接口上添加静态方法(所有以结尾的全局变量Event都是Event接口),并允许您像element.dispatchEvent(MouseEvent.create('click'));在IE9 +上那样调用函数。

(function eventCreatorWrapper(eventClassNames){
    eventClassNames.forEach(function(eventClassName){
        window[eventClassName].createEvent = function(type,bubbles,cancelable){
            var evt
            try{
                evt = new window[eventClassName](type,{
                    bubbles: bubbles,
                    cancelable: cancelable
                });
            } catch (e){
                evt = document.createEvent(eventClassName);
                evt.initEvent(type,bubbles,cancelable);
            } finally {
                return evt;
            }
        }
    });
}(function(root){
    return Object.getOwnPropertyNames(root).filter(function(propertyName){
        return /Event$/.test(propertyName)
    });
}(window)));

编辑:查找所有Event接口的函数也可以用数组替换,以仅更改所需的事件接口(['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */])。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.