未捕获的 DOMException:无法在“CustomElementRegistry”上执行“定义”:此名称已用于此注册表

Posted

技术标签:

【中文标题】未捕获的 DOMException:无法在“CustomElementRegistry”上执行“定义”:此名称已用于此注册表【英文标题】:Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': this name has already been used with this registry 【发布时间】:2019-06-10 05:33:58 【问题描述】:

在http://127.0.0.1:8000/components/@polymer/polymer/lib/elements/dom-module.js:175:16

尝试删除节点模块和包锁定并重新安装无效。

【问题讨论】:

如果我没记错的话,当我使用(至少)两个不同的路径(即使相对路径解析为相同的绝对路径)多次包含相同的元素时,我遇到了类似的错误。因此,您可以在导入元素时仔细检查是否使用相同的约定。 导入文件时遇到问题。错误现已解决。谢谢 【参考方案1】:

此错误是由于已注册的自定义元素标记名已注册;要解决此问题,只需检查该名称的元素是否尚未注册。此示例解决方案检查是否已经使用现有 API 注册了某些内容,如果没有,则注册给定的类(继承/扩展 htmlElement——在某些时候):

customElements.get('the-element') || customElements.define('the-element', HTMLTheElement);

有关 API 的更多信息,请参阅https://developer.mozilla.org/docs/Web/API/CustomElementRegistry

大多数/成熟的库都解决了这个问题,那些没有解决,或者被包和构建过程复杂性破坏的库可能会弹出它;在大多数情况下,更新到当前版本、迁移到 Lit (https://lit.dev) 或以某种方式修补问题提供了解决方案;请注意,更简单的解决方案更容易维护——从 npm, polymer 的合并中可以看出原始问题中的实际错误; Polymer 项目变成了 lit-html 和 LitElement,最近更名为“Lit”(仍然包括这些 lit-things)。从专业上讲,我正在从 npm 和 Nodejs 迁移到 Deno,目的是普遍解决与 npm 和工具不安全性和复杂性相关的许多问题,但是这个答案提供了更直接的解决方案(了解问题并直接修复,或更新到相关的最新解决方案,其中包括这个)。

【讨论】:

竖起大拇指,因为这是我见过的最好的方法。如果需要,为什么像 Polymer 这样的库没有它们?我试图避免为每个组件添加这个额外的代码 Thx @JGleason Polymer 我认为 v3 的生命周期已结束。我不确定 LitElement(afaik 是 Polymer 的继任者)做了什么,但是用 DIY 解决方案抽象出来似乎是一个简单的问题——使用基类来扩展所有内部组件,它本身很可能是现有事物的扩展,例如点亮元素。随着我们在长期的软件生命周期中迭代,这将使长期维护变得更容易。 我在没有聚合物或照明的情况下进行操作。我正在寻找更多的标准方法来处理这个仅使用规范的 Web 组件【参考方案2】:

好吧,this 为我工作,没有 Typescript 警告,

if (!customElements.get('the-element'))  customElements.define('the-element', HTMLTheElement); 

希望有人会觉得这很有用。

干杯。

【讨论】:

效果很好。干杯 在将组件作为脚本注入时使用它,效果很好【参考方案3】:

使用上面的答案是不明智的。你希望它失败!原因是您的 NPM 应该对重复的包进行重复数据删除,因此您看到在自定义元素注册表中多次定义某个组件这一事实是一个关键错误,您需要调试为什么多次注册同一个组件.

如何调试,简而言之,转到浏览器,检查元素,网络选项卡,刷新,找出哪些文件都注册了相同的元素。然后检查启动程序以查看哪些文件正在加载这些文件。然后您会更好地了解为什么您的应用没有将相同的导入解析到单个位置(您的重复数据依赖项)。

您可能会遇到此问题的一个原因是 semver。如果你有多个相同依赖项的不同主要版本,NPM 不能只是将所有安装重复数据删除到你的根 node_modules。你如何解决这个问题取决于你。有些人将 npm-aliases 用于他们不同专业的依赖项,有些人在他们的构建工具中实现一个插件来解析单个安装的路径,等等。

【讨论】:

好点,但是我在开发和热重载时使用上面的,浏览器已经注册了元素但是 customElement.define 周围的代码发生了变化, 您不理解在某些情况下可以重新调用导入。此外,您正在回答一个没有被问到的问题。虽然注意如何避免这些双重导入情况很有帮助,但它是对问题的评论而不是答案。 在使用 HMR 时,使用实际上支持自定义元素重新定义的 HMR 解决方案可能是有意义的。 modern-web.dev/docs/dev-server/plugins/hmr 仅举一个例子。如果你需要将它应用到你自己的 HMR 解决方案中,你可以使用类似 npmjs.com/package/custom-elements-hmr-polyfill 的东西,它是一个更快速和肮脏的解决方案,用一个新的 HTMLElement 扩展类重新定义你的自定义元素。 @jimmont 我确实回答了原始问题,转到您的网络选项卡并找出为什么加载了多个执行相同 customElements.define 的模块。这个问题不能用代码很好地解决,它是结构性的。例如。你需要运行 npm dedupe。或者如果这不起作用,例如您正在使用同一组件的多个主要版本,请在浏览器访问之前找到另一种解决单个安装的方法,例如使用捆绑程序插件或开发服务器插件。 这个答案有帮助。在我的例子中,它是库 @d3fc/d3fc-element,在我的 devtools 中对该库的简单搜索显示它被加载了两次(来自 npm 链接包的 node_modules)【参考方案4】:

对于由于问题出在他们的依赖项之一而无法使用@jimmonts 答案的人,您可以使用以下 sn-p:

这发生在我们身上,因为我们使用的包定义了一个元素。但是这个包被多个应用程序使用。而这些应用程序,你不知道吗,互动。所以customElements.define('x-tag', className) 被多次调用。第二次发生时,应用程序崩溃了。

function safeDecorator(fn) 
  // eslint-disable-next-line func-names
  return function(...args) 
    try 
      return fn.apply(this, args);
     catch (error) 
      if (
        error instanceof DOMException &&
        error.message.includes('has already been used with this registry')
      ) 
        return false;
      
      throw error;
    
  ;


customElements.define = safeDecorator(customElements.define);

【讨论】:

【参考方案5】:

我遇到了同样的错误。你可能和我没有同样的问题,但我想我会在这里放弃我的解决方案,以防将来有人遇到同样的问题。

我有两个模块都导入了相同的自定义元素模块,一个是导入Module.js,另一个是module.js。现在浏览器将其视为两个单独的文件,因为 URL 可以区分大小写,except 我的服务器将其视为一个文件,因为它不区分大小写 (express.js) 或至少即使大小写不正确,它也能够解析到正确文件的路径。所以浏览器看到两个“不同”的模块都定义了相同的自定义元素,但是当我搜索我的源代码时,只有一个文件定义了自定义元素。

【讨论】:

以上是关于未捕获的 DOMException:无法在“CustomElementRegistry”上执行“定义”:此名称已用于此注册表的主要内容,如果未能解决你的问题,请参考以下文章

未捕获的 DOMException:无法在“IDBObjectStore”上执行“删除”:事务未处于活动状态

未捕获的 DOMException:无法使用 JQuery 设置“innerHTML”属性

未捕获的 DOMException:无法在“CustomElementRegistry”上执行“定义”:此名称已用于此注册表

iframe chrome:未捕获的 DOMException:无法从“Window”读取“localStorage”属性:此文档的访问被拒绝

如何处理未捕获(承诺)DOMException:播放()请求被暂停()调用中断

“未捕获(承诺)的DOMException:无法为范围注册ServiceWorker”-脚本资源位于重定向后面,不允许使用