web-dev-qa-db-ja.com

モジュールシステムを使用してHTMLからTypeScript関数を呼び出す

HTMLからTypeScript(究極的にはJavaScript)関数を呼び出したいです。問題は、システムSystem(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>
_

エラーコメントは、エラーが発生した場所を示します。モジュールSystemが使用されているため、エクスポートされたクラス/関数が見つかりません。コンパイルされたjsファイルを見ると、クラスと関数の宣言がいくつかのモジュール関数内に置かれているため、HTMLからアクセスできないことがわかります。

現在、$(document).ready...セクション全体をTypeScriptファイルに移動することで回避策を使用しています。しかし、_<a href..._の例では、回避策はありません。

私の最後の質問:TypeScript関数/クラスをHTMLから呼び出し、モジュールシステムを使用することは実際に可能ですか?

9
Thomas Sparber

はい。 webpackがこれをサポートする2つの方法があります

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のトランスピレーション手順を実行する必要があるため、トリッキーになる可能性があります。他の構成によっては、上記の単純なバージョンよりも複雑になる可能性があります

したがって、私は最初のソリューションを最も簡単なものとしてお勧めします

10
alechill