简体   繁体   中英

Javascript modules import fails

I'm trying enter code here in to execute an imported module from a HTML page. I get to see that it's partially getting executed. I need help. My code files are test.html, main.js and say.js. These files are produced below in the same order.

test.html :

<html>
 <head>
     <script type="module" src="./main.js"></script>
 </head>
 <body onload="sayHi('Manish')">
 </body>
</html>

main.js :

import { sayHi } from './say.js';
sayHi('MK');

say.js :

export function sayHi(user) {
alert('Hello, { $user }');}

This code partially executes

Then after this partial execution, it gives an error

Uncaught ReferenceError: sayHi is not defined

at onload (test.html:7)

The picture of the error is as shown below:

This is the error that says sayHi function is not recognized. Why?

What am I doing wrong here?

Classic case of String interpolation

Use

export function sayHi(user) { alert(`Hello, ${user}`);}

Notice ` in place of ' or "

Reference https://campushippo.com/lessons/how-to-do-string-interpolation-with-javascript-7854ef9d

For the Error, bind the window to load

window.addEventListener("load", () => {
    sayHi('testing');
});

One of the great things about modules is that top level declarations, etc., in them don't create globals. One of the bad things about onxyz -attribute-style event handlers is that the functions you call with them have to be globals. Your sayHi isn't a global, so onload="sayHi('Manish')" fails because it doesn't have access to sayHi .

Which is a good thing.

Instead, just call the function from main.js :

import { sayHi } from './say.js';
sayHi('MK');
sayHi('Manish');

Because module scripts are automatically deferred until the end of HTML processing, you know that won't happen until all the HTML is loaded. This is covered by a great graphic in this section of the spec , duplicated here:

在此输入图像描述

If you want to wait longer, until the load event (which doesn't fire until all images and such are loaded), use a modern event handler to do that:

import { sayHi } from './say.js';
sayHi('MK');
window.addEventListener("load", () => {
    sayHi('Manish');
});

If you need information from the element you hooked the event on, use a traditional function and access the element as this , or accept the event parameter and use event.currentTarget (you can also use event.target for the element that the event targets, which could be within the element you hooked the event on). So for instance, suppose you have:

<button type="button" data-name="Manish" id="btn-say-hi">

you could have:

import { sayHi } from './say.js';
document.getElementById("btn-say-hi").addEventListener("click", function() {
    sayHi(this.getAttribute("data-name"));
});

Also note that as Vikas Saini pointed out your say.js is using a string literal instead of a template literal (and although he/she didn't mention it, also has the wrong syntax for a substitution), so you'll actually see the text Hello { $user } instead of seeing Hello MK or Hello Manish . Either use a template literal with the correct form of substitution ( ${user} , not { $user } ):

export function sayHi(user) {
    alert(`Hello, ${user}`);
}

or simple string concatenation:

export function sayHi(user) {
    alert("Hello, " + user);
}

Basically my objective was to pass some parameter from the HTML script to the main.js file. I have got the required after both of you have given me hints, especially Vikas Saini. The suggestion of adding an event listener in the main.js file helped a lot. Thanks much. I'm posting the corrected and the latest code files for the benefit of ES6 beginners like me.

The test.html file contents

<html>
<head>
    <script type="module" src="./main.js"></script>
</head>
<body>
    <input type="text" id="btn-say-hi"label="fill here" placeholder="Fill in here and click"/>
</body>
</html>

The main.js file contents

import { sayHi } from './say.js';
document.getElementById("btn-say-hi").addEventListener("click", function() {
    sayHi(this.value);
});

The say.js file contents

export function sayHi(user) { alert(`Hello, ${user}`); }

Kindly note: All these files are in the same directory/folder. I could change the text item value and could get the required execution based on my inputs.

Thanks much to TJ Crowder and a for the code snippet pertaining to adding the event listener. 提供有关添加事件监听器的代码片段。 That was a golden suggestion.

Thanks much guys. Regards Manish.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM