如何在Typescript中创建自定义事件?

New*_*016 6 typescript

如何创建customEvent Typescript并使用它?我在Mozilla网站上的javascript上找到了这个链接(https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent)

我只是在自定义事件上进行一些测试,但是Typescript将其视为错误.我计划做的是在details属性中添加一些额外的数据以便以后使用:这是我的代码.

let div:any=document.getElementById("my_div");

let c_event = new CustomEvent("build",{'details':3 });

div.addEventListener("build",function(e:Event){
    console.log(e.details);
}.bind(this));

div.dispatchEvent(c_event);
Run Code Online (Sandbox Code Playgroud)

Jur*_*els 41

接受的答案中描述的解决方案可以完成工作,但代价是失去类型安全性。

如果您想保持类型安全,我建议如下:

使用以下内容在源文件夹中创建dom.d.ts文件(或进行配置以确保 TS 编译器会在该文件夹中查找):@typestypeRoots

interface CustomEventMap {
    "customnumberevent": CustomEvent<number>;
    "anothercustomevent": CustomEvent<CustomParams>;
}
declare global {
    interface Document { //adds definition to Document, but you can do the same with HTMLElement
        addEventListener<K extends keyof CustomEventMap>(type: K,
           listener: (this: Document, ev: CustomEventMap[K]) => void): void;
        dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void;
    }
}
export { }; //keep that for TS compiler.

Run Code Online (Sandbox Code Playgroud)

这将增强的函数的全局定义,以接受您的合成事件及其类型参数。documentaddEventListener

现在你可以这样做:

function onCustomEvent(event: CustomEvent<CustomParams>){
  this.[...] // this is Document
  event.detail ... //is your CustomParams type.
}
document.addEventListener('anothercustomevent', onCustomEvent);
Run Code Online (Sandbox Code Playgroud)

这样您就可以输入并控制所有内容。

  • 为了完整性起见,进行了三个小更改。1) `addEventListener` 声明应包含第三个 `options` 参数: `options?: boolean | 添加事件监听器选项`。2) `listener` 参数的返回类型应该是 `any` 以匹配 lib.dom.d.ts 中的类型 3) 您应该包含 `removeEventListener` 的声明(包括以上几点): `removeEventListener&lt;K扩展 keyof CustomEventMap&gt;( 类型:K,侦听器:(this: HTMLElement, ev: CustomEventMap[K]) =&gt; 任何,选项?: boolean | EventListenerOptions, ): void;` (5认同)
  • 这接近我所需要的,但是使用 GlobalEventHandlersEventMap 更短并且不需要进一步的定义。在此 github 评论中找到:https://github.com/microsoft/TypeScript/issues/28357#issuecomment-748550734 (2认同)

Diu*_*lei 9

属性名称是detaildetails.正确的代码需要是:

let div: any = document.getElementById("my_div");

let c_event = new CustomEvent("build",{detail: 3});

div.addEventListener("build", function(e: CustomEvent) { // change here Event to CustomEvent
    console.log(e.detail);
}.bind(this));

div.dispatchEvent(c_event);
Run Code Online (Sandbox Code Playgroud)

  • 仅当我将“addEventListener”中的事件参数类型定义为“CustomEventInit”时,它才对我有用 (5认同)
  • 起初我认为这不起作用,但后来我发现 CustomEvent 上的 JSON.stringify() 不显示详细信息成员......叹息。 (2认同)
  • 看到这个:“与类型‘CustomEventInit&lt;unknown&gt;’没有共同的属性” (2认同)
  • `CustomEvent` 是一个泛型类型,因此在本例中,如果 `detail` 的类型为 `number`,则可以使用 `CustomEvent&lt;number&gt;`。查看答案/sf/answers/4379779771/ (2认同)
  • 我不知道这是否是 TS 版本的问题,但 CustomEvent 不起作用,CustomEventInit 会按照前面所述工作,通用是您的自定义“详细信息”的类型。 (2认同)

Mat*_*lis 9

CustomEvent是泛型类型。您可以将detail属性的类型作为参数传递(默认为any)。以下是它在lib.dom.d.ts(位于libnpm typescript 安装目录中)中的定义方式:

interface CustomEvent<T = any> extends Event {
    /**
     * Returns any custom data event was created with. Typically used for synthetic events.
     */
    readonly detail: T;
    initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: T): void;
}
Run Code Online (Sandbox Code Playgroud)

在 OP 的示例中,类型detailnumber。因此,基于@Diullei 的回答:

let div: HTMLElement | null = document.getElementById("my_div");

let c_event = new CustomEvent<number>("build", {detail: 3});

div.addEventListener("build", function(e: CustomEvent<number>) { // change here Event to CustomEvent
    console.log(e.detail);
}.bind(this));

div.dispatchEvent(c_event);
Run Code Online (Sandbox Code Playgroud)

以上,我还使用了HTMLElement从类型lib.dom.d.ts。作为 TypeScript 的新手,我发现扫描此文件并搜索“明显”类型非常有用。


sid*_*son 8

最简单的方法是这样的:

window.addEventListener("beforeinstallprompt", ((event: CustomEvent) => {
   console.log("Whoop!");
}) as EventListener);
Run Code Online (Sandbox Code Playgroud)