最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to make function calls with ES6 template literals - Stack Overflow

programmeradmin0浏览0评论

UPDATE: Here is a better example; My code is

let myFunction = () => {

    console.log('Yo');
    alert('Yo');

}

let About = {

    render : async () => {

        return /*html*/`
        <h1> About </h1>
        <button id="myBtn" type="button" >Try it</button> 

        <script>
            document.getElementById("myBtn").addEventListener ("click",  ${myFunction})
        </script>
    `
    }
}

export default About;

This transforms to the HTML code;

<div id="page_container" class="container pageEntry">
        <h1> About </h1>
        <button id="myBtn" type="button">Try it</button> 

        <script>
            document.getElementById("myBtn").addEventListener ("click",  () => {

    console.log('Yo');
    alert('Yo');

})
        </script>
    </div>

However on clicking on the button, nothing happens;


I am trying to work on a basic vanilla js SPA and I have hit a problem where I am unable to call any functions in my current module from the html code. I am using the es6 modules by specifying in my index.html that script tag is of type="module".

For example, in this code, i have tried both the inline onclick tag attribute as well as adding an event listener (i used one at a time, not together. showing it here just for illustration)

let myFunction = () => {
    console.log('Yo');
    alert('Yo');
}

let About = {

    render : async () => {

        return /*html*/`
        <h1> About </h1>
        <button id="myBtn" type="button" onclick="${myFunction}">Try it</button> 

        <script>
        document.getElementById("myBtn").addEventListener ("click",  myFunction()})
        </script>
    `
    }
}

export default About;

and I consume the resultant view as

content.innerHTML = await page.render();

from my main module.

The only way I am able to do this is by having my function call return yet another template containng the actual JS code.

let myFunction = () => {
    return `
        alert('Yo');
        document.getElementById('myBtn').textContent = 'Duh'
        `
}

however, this creates a very ugly page where my entire JS code is added inline into the HTML and that I can no longer use double quotes in my js code.

UPDATE: Here is a better example; My code is

let myFunction = () => {

    console.log('Yo');
    alert('Yo');

}

let About = {

    render : async () => {

        return /*html*/`
        <h1> About </h1>
        <button id="myBtn" type="button" >Try it</button> 

        <script>
            document.getElementById("myBtn").addEventListener ("click",  ${myFunction})
        </script>
    `
    }
}

export default About;

This transforms to the HTML code;

<div id="page_container" class="container pageEntry">
        <h1> About </h1>
        <button id="myBtn" type="button">Try it</button> 

        <script>
            document.getElementById("myBtn").addEventListener ("click",  () => {

    console.log('Yo');
    alert('Yo');

})
        </script>
    </div>

However on clicking on the button, nothing happens;


I am trying to work on a basic vanilla js SPA and I have hit a problem where I am unable to call any functions in my current module from the html code. I am using the es6 modules by specifying in my index.html that script tag is of type="module".

For example, in this code, i have tried both the inline onclick tag attribute as well as adding an event listener (i used one at a time, not together. showing it here just for illustration)

let myFunction = () => {
    console.log('Yo');
    alert('Yo');
}

let About = {

    render : async () => {

        return /*html*/`
        <h1> About </h1>
        <button id="myBtn" type="button" onclick="${myFunction}">Try it</button> 

        <script>
        document.getElementById("myBtn").addEventListener ("click",  myFunction()})
        </script>
    `
    }
}

export default About;

and I consume the resultant view as

content.innerHTML = await page.render();

from my main module.

The only way I am able to do this is by having my function call return yet another template containng the actual JS code.

let myFunction = () => {
    return `
        alert('Yo');
        document.getElementById('myBtn').textContent = 'Duh'
        `
}

however, this creates a very ugly page where my entire JS code is added inline into the HTML and that I can no longer use double quotes in my js code.

Share Improve this question edited Oct 9, 2018 at 13:17 Rishav Sharan asked Oct 9, 2018 at 12:48 Rishav SharanRishav Sharan 2,9329 gold badges42 silver badges58 bronze badges 12
  • Why do you need a template literal at all here? Can't you just do onclick="myFunction()" or addEventListener("click", myFunction)? (Note for the latter you pass the function object itself, not a call to it.) – Robin Zigmond Commented Oct 9, 2018 at 12:52
  • If i do onclick="${myFunction()}, it runs the code immediately. If I do, onclick="${myFunction}, nothing happens on click. myFunction in both cases is let myFunction = () => { alert('Yo'); } – Rishav Sharan Commented Oct 9, 2018 at 12:57
  • No, I meant drop the backticks and the $ signs, just have a literal string of HTML, including onclick="myFunction()" (escaping quotes if needed). Since it seems myFunction is the only function that you ever want to run here. Template literals are a way to embed the values of expressions inside strings, much easier than using literal strings and expressions with + inbetween them - but for this reason they're only useful if the content might change according to context. – Robin Zigmond Commented Oct 9, 2018 at 13:01
  • In that case, it is never able to find the myFunction func. It gives a Uncaught ReferenceError: myFunction is not defined at HTMLButtonElement.onclick – Rishav Sharan Commented Oct 9, 2018 at 13:06
  • oh I see, it must be that myFunction isn't in global scope. In that case then onClick won't work at all. Nor will addEventListener if it's executed from a <script> tag that you're inserting on the page. I still don't think a template literal is the way to solve this - I'd say you're better off making the addEventListener call just after you've inserted the HTML, and making sure myFunction is in scope there. Hard to know how to do it without knowing more about your code - but I'm pretty sure this isn't the kind of problem template literals were designed to solve. – Robin Zigmond Commented Oct 9, 2018 at 13:10
 |  Show 7 more comments

3 Answers 3

Reset to default 9

Here's how you can invoke a function in a template literal:

const func = () => 'Hello'

console.log(`${func()} World`)

Figured out my problem with the help of another forum.

"Scripts inserted into innerHTML don't run. You should try splitting the render function into render and onMount - the second one called just after the innerHTML line."

Architecting my app into;

let About = {
    render : async () => {
        let view =  /*html*/
            `
            <h1> About </h1>
            <button id="myBtn" type="button" >Try it</button> 
            `
        return view
    },
    after_render: async () => {
        document.getElementById("myBtn").addEventListener ("click",  () => {
            console.log('Yo')
            alert('Yo')
        })
    }

}

export default About;

and consuming it as;

content.innerHTML = await page.render();
await page.after_render();

solved my problems.

You can give the onClick a reference to your function, by not providing the () when referencing it. This will tell JavaScript to call the function and attempt to pass it the event's arguments when it gets triggered.

onclick=`${myFunction}`

will get called everytime the element is clicked.

发布评论

评论列表(0)

  1. 暂无评论