Internet Explorer 9, 10 & 11 Trình xây dựng sự kiện không hoạt động


129

Tôi đang tạo một sự kiện, vì vậy hãy sử dụng hàm tạo DOM Event:

new Event('change');

Điều này hoạt động tốt trong các trình duyệt hiện đại, tuy nhiên trong Internet Explorer 9, 10 & 11, nó không thành công với:

Object doesn't support this action

Làm cách nào tôi có thể sửa Internet Explorer (lý tưởng thông qua một polyfill)? Nếu tôi không thể, tôi có thể sử dụng cách giải quyết khác không?


55
"làm cách nào để sửa Internet Explorer?" xD
contactmatt

Câu trả lời:


176

Có một polyfill IE cho hàm tạo CustomEvent tại MDN . Thêm CustomEvent vào IE và sử dụng thay thế hoạt động.

(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
Bạn đã cứu mạng tôi. Nó sẽ được an toàn để thực hiện một sự thay thế hoàn toàn? Ý tôi là, làm window.Event= CustomEventtrên dòng cuối cùng.
tfrascaroli

7
Trong IE11 có vẻ an toàn khi đặt window.Event = CustomEvent, vâng.
Corey Alix

10
Đối với bất kỳ ai quan tâm, dường như có thể phát hiện ra bạn đang ở trong IE (đối với trường hợp này) bằng cách kiểm tra typeof (Sự kiện) là 'hàm' cho tất cả ngoại trừ IE là 'đối tượng'. Sau đó, bạn có thể điền một cách an toàn vào hàm tạo Sự kiện bằng cách sử dụng cách tiếp cận ở trên.
Euan Smith

Tôi chỉ đang điều tra cách giải quyết tương tự StorageEventtypeof(StorageEvent)không hoạt động trong MS Edge. Điều này hoạt động : try { new StorageEvent(); } catch (e) { /* polyfill */ }.
kamituel

1
Có thể không an toàn khi thay thế window.CustomEvent, nếu bạn đang sử dụng các thư viện bên thứ ba sử dụng hàm tạo CustomEvent do IE xác định.
Sen Jacob

55

Tôi nghĩ rằng giải pháp tốt nhất để giải quyết vấn đề của bạn và giải quyết việc tạo sự kiện trên nhiều trình duyệt là:

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
Nó hoạt động! Tôi chỉ nghĩ rằng nó nên return eventđể tôi có thể vượt qua nó dispatchEvent().
Noumenon

initEventđã cũ và không dùng nữa , ít nhất bạn cần sử dụng cách hiện đại và như một dự phòng, sử dụng cách không dùng nữa.
vsync

2
@vsync Có thể không được chấp nhận, nhưng các tài liệu bạn liên kết để nói "Thay vào đó hãy sử dụng các hàm tạo sự kiện cụ thể, như Event ()", đó chính xác là những gì nó đang cố gắng để polyfill, vì vậy thực sự không có lựa chọn nào.
giảm giá

1
CustomEventcho phép truyền dữ liệu tùy chỉnh thông qua detailtùy chọn và Eventkhông. Liệu tôi có sai?
pttsky

1
CustomEvent không được hỗ trợ cho IE9, 10 hoặc 11 theo kinh nghiệm của riêng tôi. Câu trả lời tốt duy nhất dường như được chấp nhận.
UndyingJellyfish

5

Gói này thực hiện điều kỳ diệu:

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

Bao gồm các gói và gửi sự kiện như sau:

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

95 phụ thuộc?
Damien Roche

4
@DamienRoche Có thể bạn đã đọc sai "Người phụ thuộc" là "Phụ thuộc"? Bởi vì gói thực sự có 0 phụ thuộc và (tại thời điểm viết) 102 phụ thuộc (nghĩa là các gói phụ thuộc vào nó). Đó là 102 gói phụ thuộc có thể là 95 trở lại vào tháng bảy.
cúm

2
Tôi cũng đã làm máu! : P
Damien Roche

3

Nếu bạn chỉ đang cố gửi một sự kiện đơn giản như sự kiện chuyển đổi HTML, thì sự kiện này hoạt động trong Internet Explorer 11 cũng như các trình duyệt khác:

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
không thể thấy lý do tại sao bạn trộn es6 let(và không sử dụng var) với mã được cho là chạy trên IE cũ .. nó có thể gây nhầm lẫn cho người mới bắt đầu sẽ sao chép-dán này
vsync

1
@vsync nhún vai tôi đã đề cập đến số phiên bản. Trang web cá nhân của tôi chỉ nhắm mục tiêu IE11 vào năm ngoái, vì vậy tôi chưa bao giờ kiểm tra hỗ trợ trong các phiên bản cũ hơn. (Kể từ hôm nay, tôi phục vụ HTML đơn giản IE11 mà không có bảng định kiểu hoặc tập lệnh. Mọi người cần phải tiếp tục.) Trong mọi trường hợp, phiên bản Internet Explorer duy nhất vẫn được Microsoft hỗ trợ kể từ tháng 4 năm 2017 là phiên bản 11, vì vậy đó là một chút điểm moot. Tôi không khuyến khích bất cứ ai sử dụng trình duyệt không được hỗ trợ bằng cách nhắm mục tiêu. Web có thể là một nơi nguy hiểm.
Patrick Dark

3
hoàn toàn không phải về điều đó, và không phải là cố gắng thay đổi thế giới hay bất cứ điều gì. Ví dụ: tiêu đề cho câu hỏi đặc biệt yêu cầu IE 9và ở trên, và có lẽ một người đang tìm câu trả lời tìm thấy chủ đề này, đang phát triển một ứng dụng cho hệ thống ngân hàng cũ hoặc một số hệ thống khác dành cho khách hàng doanh nghiệp không kiểm soát máy tính của họ và bắt buộc phải làm việc với IE cũ. điều này không liên quan gì đến bộ phận Hỗ trợ của Microsoft ..
vsync


2

các custom-eventgói NPM làm việc thật đẹp đối với tôi

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);

Đây là một câu trả lời hay, nhưng đã có một gói NPM khác được đề cập như một câu trả lời.
mikemaccana

2
Có gì sai khi cung cấp cho người dùng nhiều lựa chọn?
Liran H


1

Cá nhân tôi sử dụng chức năng bao bọc để xử lý các sự kiện được tạo thủ công. Đoạn mã sau sẽ thêm một phương thức tĩnh trên tất cả các Eventgiao diện (tất cả các biến toàn cục kết thúc bằng Eventgiao diện Sự kiện) và cho phép bạn gọi các hàm như element.dispatchEvent(MouseEvent.create('click'));trên 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)));

EDIT: Hàm tìm tất cả các Eventgiao diện cũng có thể được thay thế bằng một mảng để chỉ thay đổi các giao diện Sự kiện bạn cần ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.