Búsqueda de sitios web

javascript - Llamar a una función de typescript desde HTML usando un sistema de módulos


Me gustaría llamar a una función de TypeScript (en última instancia JavaScript) desde HTML. El problema es que también me gustaría usar un sistema de módulos (systemjs, commonjs, etc.) y también webpack.

Aquí hay un ejemplo:

ejemplo.ts:

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

example2.ts:

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

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

Los comentarios de error indican dónde ocurren los errores: la clase/función exportada no se encuentra porque se utiliza un sistema de módulos. Si miro los archivos js compilados, puedo ver que las declaraciones de clases y funciones se colocan dentro de algunas funciones de módulo, por lo que no son accesibles desde HTML.

Actualmente estoy usando una solución temporal moviendo toda la sección $ (document).ready... a un archivo TypeScript. Pero para el ejemplo <a href... no tengo ninguna solución temporal.

Así que mi pregunta final: ¿Es realmente posible llamar a una función/clase de TypeScript desde HTML y usando un sistema de módulos?

Respuesta #1

Sí. Hay 2 formas en que webpack admite esto

1) Salida usando la opción de biblioteca. Esto escribirá las exportaciones del archivo de entrada en una variable de espacio de nombres en el ámbito global que elijas

miArchivoDeEntrada.ts

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

export {
  Example,
  doSomething
}

webpack.config.js

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

Esto ahora estará disponible en window.MyExposedNamespace

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

Para un uso más avanzado, también puedes cambiar el alcance al que se aplica el espacio de nombres mediante libraryTarget, de modo que no contamine el ámbito global

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

También debes recordar importar estos archivos en algún lugar de tu proyecto, de lo contrario webpack los ignorará. No tienes que usarlos realmente, solo es para que webpack rastree las dependencias. El lugar más lógico es tu archivo de entrada

miArchivoDeEntrada.ts

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

Estos pueden entonces ser llamados a través del ámbito global (en el navegador esto es por supuesto window)

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

Este podría volverse más complicado debido a que el paso de transpiliación de TypeScript también necesita ocurrir antes de ser expuesto, lo cual, dependiendo de tu otra configuración, podría volverse más complejo que la versión simple anterior

Por lo tanto, recomendaría la primera solución como la más fácil

Artículos relacionados