无法呈现导入为模板的香草Web组件

时间:2018-12-10 15:47:16

标签: javascript html5 web-component

我正在尝试构建一个Web组件并将其导入主HTML文件中。

我的index.html

<!DOCTYPE html>
<html>
<head>
  <link rel="import" href="./tile.html">
</head>
<body>
  <a href="javascript:;" onclick="buildTile()">Build</a>

  <ns-tile /> <!-- Works -->

  <div id="ns-search-results"></div>
<script> 
  async function buildTile() { 
    const results = document.getElementById('ns-search-results'); 
    for(let i = 0; i < 10; i++) { 
      var nsTile = document.createElement('ns-tile'); 
      results.appendChild(nsTile); 
    } 
  }
</script>
</body>
</html>

tile.html

<template id="ns-item-tile"> 
  <style> </style> 
  <div class="tile"> Tile content </div>
</template>
<script> 
class NSTile extends HTMLElement { 
  constructor() {
    super();
  } 

  connectedCallback() { 
    var importedDoc = document.currentScript.ownerDocument; 
    let shadowRoot = this.attachShadow({ mode: 'open' }); 
    const t = importedDoc.querySelector('#ns-item-tile'); 
    const instance = t.content.cloneNode(true); 
    shadowRoot.appendChild(instance); 

    function init() { 
      const head = shadowRoot.querySelector('.tile'); 
      head.addEventListener("click", function () { 
        console.log('click'); 
      }); 
    } 
    init(); 
  } 
} // init the element

customElements.define("ns-tile", NSTile);
</script>

当我直接在index.html中使用<ns-tile />时,内容将正确呈现。但是,当我尝试在for方法的buildTile循环内渲染它时,出现了错误Uncaught TypeError: Cannot read property 'ownerDocument' of null at HTMLElement.connectedCallback (tile.html:16)

如何访问tile.html内的html模板,以便可以使用for循环进行构建?

1 个答案:

答案 0 :(得分:2)

几件事:

  1. 自定义元素永远不会自我关闭。 <ns-tile />应替换为<ns-tile></ns-tile>
  2. <link rel="import" href="">已死。只需正常加载脚本文件或使用ES6 Import即可。
  3. 如果您继续使用link rel="import",则必须将var importedDoc = document.currentScript.ownerDocument;移出课堂。
  4. 我看不到您在“定义”组件的任何地方:customElements.define('tag-name', className);

这是组件文件的一些更改。如果将其更改为JS文件,则它可能如下所示:

const template = `<style></style> 
<div class="tile"> Tile content </div>
`;

class NSTile extends HTMLElement { 
  constructor() {
    super();
    let shadowRoot = this.attachShadow({ mode: 'open' }); 
    shadowRoot.innerHTML = template; 

    const head = shadowRoot.querySelector('.tile'); 
    head.addEventListener("click", function () { 
      console.log('click'); 
    }); 
  } 
}

customElements.define('ns-tile', NSTile);
<ns-tile></ns-tile>