不能多次使用 Web 组件

Cannot use Web Components more than once

我是 vanilla 的新手 javascript 因为我只有 reactjs 方面的经验。我试图显示我在两个地方创建的 Web 组件。但它只显示一次。这可能是什么问题?

我的网络组件

class MyComponent extends HTMLElement {
    constructor() {
        // always call super() first
        super();
        console.log('constructed!');
    }

    connectedCallback() {
        // console.log(this.getAttribute("filter"));
        this.innerHTML = `
          <html>
            <div id="templates" class="template_style">
              <template id="book-template">
                <li><span class="title"></span> &mdash; <span class="author"></span></li>
              </template>

             <ul id="books"></ul>
           </div>

         </html>
       `;
    }
}

customElements.define('my-component', MyComponent);

用于使用数据填充 Web 组件的 JS 代码

import JsonObj from './debts.js';

const books = JsonObj;

function appendBooks() {
    const booksList = document.getElementById('books');
    const fragment = document.getElementById('book-template');

    // Clear out the content from the ul
    booksList.innerHTML = '';
    console.log(books);
    // Loop over the books and modify the given template
    books.debts.forEach(book => {
        // Create an instance of the template content
        const instance = document.importNode(fragment.content, true);
        // Add relevant content to the template
        instance.querySelector('.title').innerHTML = book.bank;
        instance.querySelector('.author').innerHTML = book.category;
        // Append the instance ot the DOM
        booksList.appendChild(instance);
    });
}


document.getElementById('templates').addEventListener('change', (event) => appendBooks());

appendBooks('book-template');

HTML 我使用上述组件的代码

<div>

    <div class="sub_container">

        <label>Users in Debt</label>

        <input placeholder="Search by user name" class="input_style">

        <my-component filter="userdebt"></my-component>


    </div>

    <div class="sub_container">

        <label>Debts</label>

        <input placeholder="Search by debt description" class="input_style">

        <my-component filter="debt"></my-component>

    </div>

</div>

因此,正如在 html 代码中看到的那样,我在两个地方使用了 </my-component>,但我只能看到第一个实例。我在我的组件中使用了 console.log 内部构造函数,我可以看到它调用了 2 次。但在视图中我只能看到第一个实例。我该如何解决这个问题?

我已经在 codepen 中重复了你的代码,它的工作如你所愿。生成两个组件。如果有,您应该检查其他地方是否有错误。 并且不要因为重复而在组件中使用静态 ID。 HTML标签也不需要使用。

您应该将 id 添加到 web-component 本身,以便您可以使用 parent 的 id 查询 child 节点包含在其中

在您的代码中,当使用 web-component 的 child 的 id 查询时,它为您获取了第一个,因为您有重复的 ID,在我的代码中,我给了每个<my-component> 标记一个唯一的 id 这样我就只能查询它的 child:

class MyComponent extends HTMLElement {
    constructor() {
        // always call super() first
        super();
        console.log('constructed!');
    }

    connectedCallback() {
        // console.log(this.getAttribute("filter"));
        this.innerHTML = `
            <div id="templates" class="template_style">
              <template id="book-template">
                <li><span class="title"></span> &mdash; <span class="author"></span></li>
              </template>

             <ul id="books"></ul>
           </div>
       `;
    }
}

customElements.define('my-component', MyComponent);
const books = [{bank : "foo", category: "bar"}];

function appendBooks(id) {
    const comp = document.getElementById(id);
    //query for the child of the parent web-component
    const booksList = comp.querySelector('#books'); 
    const fragment = comp.querySelector('#book-template');
   

    // Clear out the content from the ul
    booksList.innerHTML = '';
   
    // Loop over the books and modify the given template
    books.forEach(book => {
        // Create an instance of the template content
        const instance = document.importNode(fragment.content, true);
        // Add relevant content to the template
       
        instance.querySelector('.title').innerHTML = book.bank;
        instance.querySelector('.author').innerHTML = book.category;
        // Append the instance ot the DOM
        booksList.appendChild(instance);
    });
}

function addChangeListener(id){
  document.getElementById(id)
          .querySelector('#templates')
          .addEventListener('change', (event) => appendBooks());
}

appendBooks('comp1'); //for componenent having id = comp1
appendBooks('comp2'); //for componenent having id = comp2
addChangeListener('comp1')
addChangeListener('comp2')
<div>

    <div class="sub_container">

        <label>Users in Debt</label>

        <input placeholder="Search by user name" class="input_style">

        <my-component id="comp1" filter="userdebt"></my-component>


    </div>

    <div class="sub_container">

        <label>Debts</label>

        <input placeholder="Search by debt description" class="input_style">

        <my-component id="comp2" filter="debt"></my-component>

    </div>

</div>