Search code examples
javascriptwebweb-component

previous custom element overwrited by next elements when import serval webcomponent


when multiple custom element in a single page, why always show the last element and the previous element is overwrited. for example:

first component:

<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>

second component:

<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>

when import these two component in single page,such as that:

import above component

<!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>

then only show "component 2", the second element overwrite the first element .


Solution

  • Wrapping codes in the script tag in a immediately invoked function expression to confine scopes solves your problem.

    <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>

    It is the same for 'cmpt-1'.