如何将 Web 组件分离到单个文件并加载它们?

Posted

技术标签:

【中文标题】如何将 Web 组件分离到单个文件并加载它们?【英文标题】:How to separate web components to individual files and load them? 【发布时间】:2019-07-31 11:35:33 【问题描述】:

我有一个 Web 组件 x-counter,它在一个文件中。

const template = document.createElement('template');
template.innerhtml = `
  <style>
    button, p 
      display: inline-block;
    
  </style>
  <button aria-label="decrement">-</button>
    <p>0</p>
  <button aria-label="increment">+</button>
`;

class XCounter extends HTMLElement 
  set value(value) 
    this._value = value;
    this.valueElement.innerText = this._value;
  

  get value() 
    return this._value;
  

  constructor() 
    super();
    this._value = 0;

    this.root = this.attachShadow( mode: 'open' );
    this.root.appendChild(template.content.cloneNode(true));

    this.valueElement = this.root.querySelector('p');
    this.incrementButton = this.root.querySelectorAll('button')[1];
    this.decrementButton = this.root.querySelectorAll('button')[0];

    this.incrementButton
      .addEventListener('click', (e) => this.value++);

    this.decrementButton
      .addEventListener('click', (e) => this.value--);
  


customElements.define('x-counter', XCounter);

这里的模板被定义为使用 javascript 并且 html 内容被添加为内联字符串。有没有办法将模板分离到 x-counter.html 文件,css 说,x-counter.css 和相应的 JavaScript 代码到 xcounter.js 并将它们加载到 index.html 中?

我查找的每个示例都混合了 Web 组件。我想分离关注点,但我不知道如何用组件做到这一点。你能提供一个示例代码吗?谢谢。

【问题讨论】:

【参考方案1】:

在主文件中,使用&lt;script&gt;加载Javascript文件x-counter.js

在Javascript文件中,使用fetch()加载HTML代码x-counter.html

在 HTML 文件中,使用 &lt;link rel="stylesheet"&gt; 加载 CSS 文件 x-counter.css

CSS 文件:x-counter.css

button, p 
    display: inline-block;
    color: dodgerblue;

HTML 文件:x-counter.html

<link rel="stylesheet" href="x-counter.css">
<button aria-label="decrement">-</button>
    <p>0</p>
<button aria-label="increment">+</button>

Javascript 文件:x-counter.js

fetch("x-counter.html")
    .then(stream => stream.text())
    .then(text => define(text));

function define(html) 
    class XCounter extends HTMLElement 
        set value(value) 
            this._value = value;
            this.valueElement.innerText = this._value;
        

        get value() 
            return this._value;
        

        constructor() 
            super();
            this._value = 0;

            var shadow = this.attachShadow(mode: 'open');
            shadow.innerHTML = html;

            this.valueElement = shadow.querySelector('p');
            var incrementButton = shadow.querySelectorAll('button')[1];
            var decrementButton = shadow.querySelectorAll('button')[0];

            incrementButton.onclick = () => this.value++;
            decrementButton.onclick = () => this.value--;
        
    

    customElements.define('x-counter', XCounter);

主文件:index.html

<html>
<head>
    <!-- ... -->
    <script src="x-counter.js"></script>
</head>
<body>
    <x-counter></x-counter>
</body>
</html>

【讨论】:

非常好的答案!假设您想对 x-count.js Web 组件进行单元测试?你会怎么做?例如,如果您想使用 karma 进行非常基本的单元测试,只是为了检查 web 组件是否已呈现,如何实现呢? @JimC 我不使用 Karma,但我想您可以像检查任何其他元素一样检查自定义元素的 html 内容。我知道你可以用 Chai.js + Selenium Webdriver 做到这一点。 我写了一篇 Medium 文章 - 有一个可能的解决方案 roshan-khandelwal.medium.com/web-components-c7aef23fe478 我在尝试将 html 文件获取到 Chrome 扩展程序中的 js 类时收到 TypeError: failed to fetch

以上是关于如何将 Web 组件分离到单个文件并加载它们?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 React 组件分离到不同的文件中以使其正常工作并避免 TypeErrors?

如何将输入/选择值从网站保存到 XML/JSON 文件并使用 JavaScript 自动加载再次填充它们

为啥在 React.js 中为组件使用单独的 CSS 文件

如何遍历 Excel 文件并使用 SSIS 包将它们加载到数据库中?

如何将第 3 方脚本从 Web 动态加载到 Angular2 组件中

如何加快 Angular 7 中初始加载的加载时间?