【问题标题】:Calling typescript function from HTML using a module system使用模块系统从 HTML 调用 typescript 函数
【发布时间】:2018-01-10 09:18:09
【问题描述】:

我想从 HTML 调用 TypeScript(最终是 JavaScript)函数。问题是我还想使用模块系统(systemjs、commonjs 等)和 webpack。

这是一个例子:

example.ts:

export class Example {
    myFunction() {
        alert('Test');
    }
}

example2.ts:

export function doSomething() {
    alert('Test2');
}

example.html:

<html>
    <head>
        <script src="path/to/the/compiled/js/file.js"></script>
        <script>
            $(document).ready(function() {
                $('#test-btn').click(function(){
                    var example = new Example(); //error1
                    example.myFunction();
                });
            });
        </script>
    </head>
    <body>
        <button id="test-btn">Click me</button>
        <a href="javascript:doSomething()">Click me too</a> <!-- error2 -->
    </body>
</html>

错误 cmets 指示错误发生的位置:未找到导出的类/函数,因为使用了模块 System。如果我查看编译后的 js 文件,我可以看到类和函数声明放在一些模块函数中,因此无法从 HTML 访问它们。

目前我正在使用解决方法,将整个 $(document).ready... 部分移动到 TypeScript 文件中。但对于 &lt;a href... 示例,我没有任何解决方法。

所以我的最后一个问题:实际上是否可以从 HTML 调用 TypeScript 函数/类并使用模块 System?

【问题讨论】:

  • 您可以为侦听message 事件的全局函数创建一个单独的文件。那些会广播到你的打字稿应用程序。
  • @DanielLizik 谢谢这是个好主意!但我认为这只是另一个黑客。没有“正确”的方法吗?
  • IMO 这是“正确”的方式。它使您的window 对象不受污染并消除您的顾虑。

标签: javascript html typescript systemjs commonjs


【解决方案1】:

是的。 webpack 有两种方式支持这个

1) 使用library 选项输出。这会将入口文件的导出写入您选择的全局范围内的命名空间变量

myEntryFile.ts

import {Example} from './example'
import {doSomething} from './example2'

export {
  Example,
  doSomething
}

webpack.config.js

output: {
  //... your normal output config her
  library: 'MyExposedNamespace'
}

现在可通过window.MyExposedNamespace 获得此功能

window.MyExposedNamespace.doSomething()
const myExample = new window.MyExposedNamespace.Example()

对于更高级的用法,您还可以通过libraryTarget 更改应用命名空间的范围,这样就不会污染全局范围

2) 使用expose-loader

webpack.config.js

module: {
  rules: [
    { test: /example\.ts$/, 
      use: [
       { loader: 'expose-loader', options: 'Example'},
       'awesome-typescript-loader' // must transpile as file is typescript
      ]
    },
    { test: /example2\.ts$/, 
      use: [
        { loader: 'expose-loader', options: 'doSomeThing'},
        'awesome-typescript-loader'
      ]
    }
  ]
}

你还必须记住在你的项目中的某个地方导入这些文件,否则 webpack 会忽略它们。您不必实际使用它们,它只是用于 webpack 跟踪依赖关系。最合乎逻辑的地方是你的入口文件

myEntryFile.ts

import './example'
import './example2'

然后可以通过全局范围调用这些(在浏览器中当然是window

window.doSomeThing()
const myExample = new window.Example()

这可能会变得更棘手,因为在暴露之前还需要进行 typescript 转换步骤,这取决于您的其他配置,可能会比上面的简单版本更复杂

因此我建议第一个解决方案是最简单的

【讨论】:

  • 非常好,非常感谢!这正是我想要的。还有一个问题:webpack 是否也可以导出外部库?这样我就可以使用例如我的 html 文件中也有 jquery?
  • 是的,如果你把它安装为一个节点模块,你可以添加一个加载器来暴露它{ test: require.resolve('jquery'), use: { loader: 'expose-loader', options: 'myExposedJqueryInstance'} }
猜你喜欢
  • 2018-05-06
  • 2020-04-25
  • 2017-01-11
  • 1970-01-01
  • 2020-01-02
  • 2017-11-20
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
相关资源
最近更新 更多