web-dev-qa-db-ja.com

ES6モジュール:インポート後の未定義のonclick関数

ES6モジュールをテストしており、ユーザーがonclickを使用してインポートされた関数にアクセスできるようにしたい:

test.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Module Test</title>
</head>
<body>
    <input type="button" value="click me" onclick="hello();"/>
    <script type="module">import {hello} from "./test.js";</script>
</body>
</html>

test.js:

export function hello() {console.log("hello");}

ボタンをクリックすると、開発者コンソールに「ReferenceError:hello is not defined」と表示されます。 onclick関数として使用できるように、モジュールから関数をインポートするにはどうすればよいですか?

dom.moduleScripts.enabledtrueに設定してFirefox 54.0を使用しています。

18
Konrad Höffner

モジュールは、名前の衝突を避けるためにスコープを作成します。

関数をwindowオブジェクトに公開する

import {hello} from './test.js'

window.hello = hello

または、addEventListenerを使用してハンドラーをバインドします。 デモ

<button type="button" id="hello">Click Me</button>
<script type="module">
  import {hello} from './test.js'

  document.querySelector('#hello').addEventListener('click', hello)
</script>
35
Yury Tarabanko

_ES6_モジュールのモジュールスコープ:

_type="module"_を使用して次の方法でスクリプトをインポートする場合:

_<script type="module">import {hello} from "./test.js";</script>
_

モジュールスコープと呼ばれる特定のスコープを作成しています。ここで、モジュールのスコープは他のレベルのスコープに関連しています。グローバルから始まります:

  1. グローバルスコープ:最も外側のレベルのモジュール外(つまり、関数内ではなく、constおよびlet forブロック内)のすべての宣言は、Javascriptランタイム環境のどこからでもアクセスできます。
  2. モジュールスコープ:モジュール内のすべての宣言は、モジュールにスコープされます。他のjavasciptがこれらの宣言にアクセスしようとすると、参照エラーがスローされます。
  3. 関数スコープ:関数本体(の最上位)内で宣言されたすべての変数は関数スコープです
  4. ブロックスコープ:letおよびconst変数はブロックスコープです

モジュールでhello()関数が宣言されたため、referenceErrorが発生していました。これはmodule scopedでした。前に見たように、モジュールスコープ内の宣言はそのモジュール内でのみ利用可能であり、モジュールを使用してそれを使用しようとしました。

explicitlywindowオブジェクトに置くと、モジュールの外側で使用できるように、モジュール内で宣言を行うことができます。例えば:

_window.hello = hello;  // putting the hello function as a property on the window object
_
3