如何使用ES6模板字面量进行函数调用

9

更新: 这里有一个更好的例子; 我的代码是:

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;

这将转换为HTML代码;
<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>

然而,当点击按钮时,没有任何反应;


我正在尝试开发一个基本的纯JS SPA,但是遇到了一个问题,即我无法从HTML代码中调用当前模块中的任何函数。 我使用ES6模块,通过在index.html中指定脚本标记为 type="module" 来进行设置。

例如,在此代码中,我尝试了内联 onclick 标签属性以及添加事件监听器(一次只用一种方法,不会同时使用)。这里只是为了说明问题。

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;

我将结果视图作为消耗品。

content.innerHTML = await page.render();

来自我的主模块。

我能够做到的唯一方法是通过让我的函数调用返回另一个包含实际JS代码的模板。

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

然而,这会创建一个非常丑陋的页面,其中我的整个JS代码都内联添加到HTML中,我无法在JS代码中再使用双引号。

你为什么需要在这里使用模板文字?你不能只是做 onclick="myFunction()" 或者 addEventListener("click", myFunction) 吗?(注意,对于后者,你传递的是函数对象本身,而不是函数调用。) - Robin Zigmond
不,我的意思是去掉反引号和$符号,只使用HTML的字面字符串,包括onclick="myFunction()"(如果需要转义引号)。因为似乎myFunction是您想要在此运行的唯一函数。模板字面量是一种将表达式的值嵌入字符串中的方法,比使用字面字符串和表达式之间的+更容易 - 但出于这个原因,它们仅在内容可能根据上下文而变化时才有用。 - Robin Zigmond
在这种情况下,它永远无法找到myFunction函数。它会给出一个“未捕获的引用错误:myFunction未定义”,位于HTMLButtonElement.onclick处。 - Rishav Sharan
哦,我明白了,肯定是myFunction不在全局作用域中。在这种情况下,onClick将完全无效。如果您从要插入到页面上的<script>标记中执行addEventListener,则此操作也将无效。我仍然认为模板文字不是解决此问题的方法-我建议在插入HTML后立即调用addEventListener,并确保myFunction在那里是可用的。很难在不了解您的代码更多信息的情况下知道如何做到这一点-但我很确定这不是设计模板字面量来解决的问题类型。 - Robin Zigmond
页面源代码没有显示JS生成的内容,但是Web工具节点元素显示了生成的HTML。我从那里复制粘贴。我认为事件监听器由于某些原因未被添加。 - Rishav Sharan
显示剩余7条评论
3个回答

9

以下是如何在模板字面量中调用函数的方法:

const func = () => 'Hello'

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


2
这是不正确的,它会插入函数的返回值而不是函数本身。 - braks

5

在另一个论坛的帮助下,我解决了我的问题。

“插入innerHTML的脚本不会运行。您应该尝试将渲染函数分为render和onMount-第二个函数在innerHTML行后立即调用。”

将我的应用程序架构化为;

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;

并将它消耗为;

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

解决了我的问题。

接受您的答案以便未来的观众。 - Syed M. Sannan

2

当引用函数时,可以通过不提供()的方式为onClick提供一个对函数的引用。这会告诉JavaScript,在触发事件时调用该函数并尝试将事件参数传递给它。

onclick=`${myFunction}`

每次点击该元素时,都将调用此函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接