如何将模块导出的函数导入HTML onclick =“”事件处理程序的全局范围?

时间:2019-02-21 10:13:21

标签: javascript module systemjs

一个使用SystemJS 0.21的简单HTML网页,该网页正在加载从TypeScript编译的JavaScript模块。 HTML网页具有onclick=""样式的事件处理程序,该事件处理程序调用在模块文件中声明的函数:

tsconfig.json

{
    "compilerOptions": {
        "module": "system",
        "moduleResolution": "node"
    }
}

Page.ts

export function onButtonClick( e: Event, btn: HTMLButtonElement ): boolean {

    console.log( 'clicked!' );
    return true;
}

我在网站(不是SPA)的HTML页面中使用SystemJS,如下所示:

system.config.js

System.config( {

    map: { /* ... */ },

    packages: {
        '/scripts/': { defaultExtension: 'js' }
    }

} );

System.import( '/scripts/Page' );

Page.html

<html>
<head>
    <script src="/scripts/system.src.js"></script>
    <script src="/scripts/system.config.js"></script>
</head>
<body>

    <button onclick="onButtonClick( event, this )">Click me and check the browser console</button>

</body>
</html>

这不起作用,因为onButtonClick函数在Page.js中定义为模块内的函数,这意味着它不作为属性导入到全局(Window)中使用脚本中的对象。因此,我在控制台窗口中得到了以下输出:

  

未捕获的ReferenceErroronButtonClick在HTMLButtonElement.onclick(Page.html:8)上未定义

那么我如何让<button onclick="onButtonClick( event, this )"function onButtonClick / Page.ts中使用Page.js

1 个答案:

答案 0 :(得分:0)

我现在开发了一种解决方法:

  1. 在TypeScript模块中扩展全局Window对象接口,以添加新的全局函数。
  2. 在模块的“顶层”函数中的window上分配那些声明的函数属性。

这与SystemJS将模块导入 window对象(这是我最初想要的)不同,而且这种方法还需要我修改模块正在导入,但目前仍适用。

像这样:

Page.ts

declare global {
    declare interface Window {
        onButtonClick( e: Event, btn: HTMLButtonElement ): boolean;
    }
}

function onButtonClick( e: Event, btn: HTMLButtonElement ): boolean {

    console.log( 'clicked!' );
    return true;
}

window.onButtonClick = onButtonClick;

不再需要导出onButtonClick函数。只需直接分配该功能,就可以更加简洁:

Page.ts

declare global {
    declare interface Window {
        onButtonClick( e: Event, btn: HTMLButtonElement ): boolean;
    }
}

window.onButtonClick = onButtonClick( e: Event, btn: HTMLButtonElement ): boolean {

    console.log( 'clicked!' );
    return true;
};

因为Page.ts / Page.js模块是异步加载的,这的确意味着Page.html属性在加载onclick=""之前不会起作用,但是假设页面加载后很快就会发生,不会有任何用户体验问题。