web-dev-qa-db-fra.com

Appel de la fonction TypeScript depuis HTML à l'aide d'un système de modules

Je voudrais appeler une fonction TypeScript (ultimement JavaScript) à partir de HTML. Le problème est que j'aimerais aussi utiliser un module système (systemjs, commonjs etc.) et aussi webpack.

Voici un exemple:

example.ts:

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

example2.ts:

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

exemple.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>

Les commentaires d'erreur indiquent où les erreurs se produisent: La classe/fonction exportée est introuvable car un module System est utilisé. Si je regarde dans les fichiers js compilés, je peux voir que les déclarations de classe et de fonction sont placées dans certaines fonctions de module, donc elles ne sont pas accessibles depuis HTML.

Actuellement, j'utilise une solution de contournement en déplaçant l'intégralité de la section $(document).ready... dans un fichier TypeScript. Mais pour l'exemple <a href..., Je n'ai aucune solution de contournement.

Donc ma dernière question: est-il réellement possible d'appeler une fonction/classe TypeScript depuis HTML et en utilisant un module System?

9
Thomas Sparber

Oui. Il y a 2 façons dont webpack prend en charge cela

1) Sortie à l'aide de l'option bibliothèque . Cela va écrire les exportations du fichier d'entrée dans une variable d'espace de noms dans la portée globale de votre choix

myEntryFile.ts

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

export {
  Example,
  doSomething
}

webpack.config.js

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

Il sera désormais disponible sur window.MyExposedNamespace

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

Pour une utilisation plus avancée, vous pouvez également modifier la portée à laquelle l'espace de noms est appliqué via libraryTarget afin de ne pas polluer la portée globale

2) Utilisation de 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'
      ]
    }
  ]
}

Vous devez également vous rappeler d'importer ces fichiers quelque part dans votre projet, sinon webpack les ignorera. Vous n'avez pas besoin de les utiliser, c'est juste pour que webpack trace les dépendances. L'endroit le plus logique est votre fichier d'entrée

myEntryFile.ts

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

Ceux-ci peuvent ensuite être appelés via la portée globale (dans le navigateur, c'est bien sûr window)

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

Celui-ci peut devenir plus délicat car l'étape de transpilation TypeScript doit également se produire avant d'être exposée, ce qui, selon votre autre configuration, pourrait devenir plus complexe que la version simple ci-dessus

Je recommanderais donc la première solution comme la plus simple

10
alechill