导入 serval WebComponent 时,上一个自定义元素被下一个元素覆盖

previous custom element overwrited by next elements when import serval webcomponent

本文关键字:元素 下一个 覆盖 自定义 上一个 serval WebComponent 导入      更新时间:2023-09-26

当单个页面中有多个自定义元素时,为什么总是显示最后一个元素而上一个元素被覆盖。 例如:

第一个组件:

<template id="cmpt-1">
  webcomponent 1
</template>
<script type="text/javascript">
  var thatDoc = document;
  var thisDoc = (thatDoc._currentScript || thatDoc.currentScript).ownerDocument;
  var t = thisDoc.querySelector('#cmpt-1');
  var protos = Object.create(HTMLElement.prototype, {
    createdCallback: {
      value: function() {
        var clone = thatDoc.importNode(t.content, true);
        this.createShadowRoot().appendChild(clone);
      }
    }
  });
  thatDoc.registerElement('cmpt-1', {
    prototype: protos
  }); 
</script>

第二个组件:

<template id="cmpt-2">
  webcomponent 2
</template>
<script type="text/javascript">
  var thatDoc = document;
  var thisDoc = (thatDoc._currentScript || thatDoc.currentScript).ownerDocument;
  var t = thisDoc.querySelector('#cmpt-2');
  var protos = Object.create(HTMLElement.prototype, {
    createdCallback: {
      value: function() {
        var clone = thatDoc.importNode(t.content, true);
        this.createShadowRoot().appendChild(clone);
      }
    }
  });
  thatDoc.registerElement('cmpt-2', {
    prototype: protos
  }); 
</script>

在单个页面中导入这两个组件时,例如:

导入上述组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <link rel="import" href="cmpt1.html">
  <link rel="import" href="cmpt2.html">
</head>
<body>
  <cmpt-1></cmpt-1>
  <cmpt-2></cmpt-2>
</body>
</html>

然后只显示"组件2",第二个元素覆盖第一个元素。

将脚本标记中的代码包装在立即调用的函数表达式中以限制范围可以解决您的问题。

<template id="cmpt-2">
    webcomponent 2
</template>
<script type="text/javascript">
    (function() {
        var thatDoc = document;
        var thisDoc = (thatDoc._currentScript || thatDoc.currentScript).ownerDocument;
        var t = thisDoc.querySelector('#cmpt-2');
        var protos = Object.create(HTMLElement.prototype, {
            createdCallback: {
                value: function() {
                    var clone = thatDoc.importNode(t.content, true);
                    this.createShadowRoot().appendChild(clone);
                }
            }
        });
        thatDoc.registerElement('cmpt-2', {
            prototype: protos
        });
    })();
</script>

"cmpt-1"也是如此。

您在全局范围内定义所有变量 - 两次,实际上protos在呈现组件时是指向第二个组件的指针。快速修复是将每个protos重命名为合理的名称,例如 cmpt1cmpt2 ,并在 thatDoc.registerElement 中引用正确的 var。更好的解决方案是创建一个初始化自定义组件的泛型函数,并完全避免全局范围。