首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >直接在html中使用ES6模块中定义的参数化函数。

直接在html中使用ES6模块中定义的参数化函数。
EN

Stack Overflow用户
提问于 2021-10-26 09:30:33
回答 2查看 138关注 0票数 1

嵌入在HTML中的ES6模块中定义的函数对该脚本不可用。因此,如果您有如下语句:

<button onclick="doSomething();">Do something</button>

在HTML和doSomething()函数中,在HTML脚本中嵌入的ES6模块中,在运行脚本时会出现一个"doSomething()是未定义的“错误。

直接在html中使用ES6模块中定义的函数为当前问题提出了一个很好的解决方案,建议您通过修改HTML将函数“绑定”到按钮上:

<button id="dosomethingbutton">Do something</button>

并使用模块本身创建链接:

document.getElementById('dosomethingbutton').addEventListener('click', doSomething);

这很好,但是如果您的原始按钮更复杂一些,并且是参数化的呢?例如:

<button onclick="doSomething('withThisString');">Do Something with String</button>

“绑定”所能提供的最大限度似乎仅限于与事件相关的情况--我无法找到将其与数据相关联的方法。我完全被困在试图找到解决这个问题的办法,并将非常感谢的帮助。

我想补充一点,虽然这个问题看起来有点模糊,但我认为任何迁移到Firebase 9的人都会对它感兴趣。迁移要求您将javascript代码移动到ES6模块中(在该模块中,HTML不能直接使用名称空间),因此最简单的HTML可能会立即遇到这些问题。非常欢迎你提出建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-10-26 09:35:39

这很好,但是如果您的原始按钮更复杂一些,并且是参数化的呢?

这方面有几个解决办法:

  1. data-*属性: 用绳子做某事 document.getElementById("the-button").addEventListener("click",函数(){ doSomething(this.getAttribute("data-string"));}; (下文将对此作更多介绍。) 或
  2. 绑定事件时绑定字符串 用绳子做某事 document.getElementById("the-button").addEventListener("click",() => { doSomething("withThisString");};

上面有很多变体,如果使用带有不同字符串的多个按钮的doSomething,您可以使用类和循环来执行#1,而不是使用id,但这是一般的想法。

关于data-*属性的事情:如果您愿意,您可以通过data-*属性和一个连接起来的单一函数,使这个过程完全由data-*驱动。例如,假设您有以下按钮:

代码语言:javascript
复制
<button data-click="doThisx@module1">Do This</button>
<button data-click="doThat@module2">Do That</button>
<button data-click="doTheOther@module3">Do The Other</button>

您可以使用一个可重用的函数将其连接起来:

代码语言:javascript
复制
class EventSetupError extends Error {
    constructor(element, msg) {
        if (typeof element === "string") {
            [element, msg] = [msg, element];
        }
        super(msg);
        this.element = element;
    }
}
export async function setupModuleEventHandlers(eventName) {
    try {
        const attrName = `data-${eventName}`;
        const elements = [...document.querySelectorAll(`[${attrName}]`)];
        await Promise.all(elements.map(async element => {
            const attrValue = element.getAttribute(`data-${eventName}`);
            const [fname, modname] = attrValue ? attrValue.split("@", 2) : [];
            if (!fname || !modname) {
                throw new EventSetupError(
                    element,
                    `Invalid '${attrName}' attribute "${attrValue}"`
                );
            }
            // It's fine if we do import() more than once for the same module,
            // the module loader will return the same module
            const module = await import(`./${modname}.js`);
            const fn = module[fname];
            if (typeof fn !== "function") {
                throw new EventSetupError(
                    element,
                    `Invalid '${attrName}': no '${fname}' on module '${modname}' or it isn't a function`
                );
            }
            element.addEventListener(eventName, fn);
        }));
    } catch (error) {
        console.error(error.message, error.element);
    }
}

使用它查找并挂起单击处理程序:

代码语言:javascript
复制
import { setupModuleEventHandlers } from "./data-attr-event-setup.js";
setupModuleEventHandlers("click")
.catch(error => {
    console.error(error.message, error.element);
});

这是一次性的管道,但在HTML中提供了相同的基于属性的体验(事件处理程序仍然可以从另一个data-*属性获取参数信息,或者您可以将其放入安装函数中)。(该示例依赖于import,但这是所有主要浏览器的最新版本都支持,并在不同程度上依赖于绑定器。

有几十种方法来旋转它,我并不是在推广它,只是举一个例子,如果你愿意的话,你可以很容易地做一些事情。

但实际上,这是像React,Vue,Ember,角,Lit等图书馆发挥作用的地方。

票数 1
EN

Stack Overflow用户

发布于 2021-10-30 18:00:09

虽然T.JCrowder已经回答了这个问题,但我想我可能会添加一些很难作为评论的要点。

当我深入到Firebase V9转换中时,我开始发现“模块名称空间”问题的一些后果相当深远。我在最初的问题中引用的示例很容易处理,但我发现我还需要计算出如何处理响应于数据库中的可变环境的“动态”HTML。在这种情况下,我的javascript最初应该创建一个包含HTML块的字符串,如:

代码语言:javascript
复制
realDiv = `
<div>
    <button onclick = "function fn1 (param1a, param1b,...);">button1</button>
    <button onclick = "function fn2 (param2a, param2b,...);">button2</button>
etc
</div>
`

,然后将其抛到应用程序的HTML框架中定义的“真实”realdiv中。

document.getElementById("realdiv") = realDiv;

现在,由于上述原因,一旦javascript在模块中,这种安排就不再有效。

我学会采用的模式(再次感谢T.J·克劳德)大致如下:

代码语言:javascript
复制
realDiv = `
<div>
    <button id = "button1" data-param1a="param1a" data-param1b="param1b";">button1</button>
    <button id = "button2" data-param2a="param2a" data-param2b="param2b";">button2</button>
etc
</div>
`

然后,我会像以前一样将生成的代码放入HTML框架中。

document.getElementById("realdiv") = readlDiv;

现在,您已经将代码嵌入到DOM中(假设我对您生成的按钮数量进行了计数),我将使用最后一点javascript为它们创建绑定,如下所示:

代码语言:javascript
复制
for (let i = 0; i>buttonCount; i++) {
    document.getElementById('button' + i).onclick = function() { fn1 (this.getAttribute('data-param1a'), this.getAttribute('data-param1b') };
etc
}

我发现当我需要让onclick启动许多不同的功能时,用这种模式创建onclick对于保持清晰性特别有帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69720620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档