问题描述
一个使用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 )对象中。
所以我在控制台窗口中得到以下输出:
onButtonClick捕获的ReferenceError:onButtonClick(Page.html:8)上未定义onButtonClick
那么,如何在Page.ts / Page.js使用<button onclick="onButtonClick( event, this )"来使用function onButtonClick呢?
1楼
Dai
0
2019-02-22 02:48:45
我现在开发了一种解决方法:
-
在TypeScript模块中扩展全局
Window对象接口,以添加新的全局函数。 -
在模块的“顶层”函数内的
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=""属性将在模块加载之前不起作用-但假设在页面加载后很快发生,不会有任何用户体验问题。