利用 Custom Elements 和 Shadow DOM 创建可复用的 UI 组件

随着 Web 应用的日益复杂,我们需要大量的 UI 组件来构建页面。然而,传统的开发方式往往会导致代码混乱,维护成本高,且无法实现组件的复用。这时,我们可以利用浏览器原生的 Custom Elements 和 Shadow DOM API 来创建可复用的 UI 组件。

Custom Elements

Custom Elements API 允许我们创建自定义元素,这些元素可以像普通 HTML 元素一样使用,同时可以自定义其功能和样式。

定义自定义元素

使用 Custom Elements API 定义自定义元素非常简单。我们只需要继承 HTMLElement 类,然后使用 customElements.define() 方法将其与自定义标签进行关联即可。

class MyElement extends HTMLElement {
  constructor() {
    super();
    // 在这里构建元素的 Shadow DOM
  }
}
customElements.define('my-element', MyElement);

在上述代码中,我们定义了一个名为 MyElement 的类,它继承自 HTMLElement。在类的构造函数中,我们可以构建元素的 Shadow DOM。最后,使用 customElements.define() 方法将 MyElement 与自定义标签 my-element 进行关联。

使用自定义元素

定义自定义元素之后,我们就可以像使用普通 HTML 元素一样使用它了。

<my-element></my-element>

自定义元素的生命周期

自定义元素有以下几个生命周期:

  • constructor(): 构造函数,用于初始化元素。
  • connectedCallback(): 元素插入文档时调用,用于初始化 Shadow DOM 和添加事件监听器等操作。
  • disconnectedCallback(): 元素从文档中删除时调用,用于清理元素。
  • attributeChangedCallback(name, oldValue, newValue): 属性值发生变化时调用,用于更新元素状态。

在自定义元素中,我们可以使用这些生命周期方法来实现各种功能,例如:创建 Shadow DOM、添加事件监听器、响应属性变化等。

Shadow DOM

Shadow DOM API 允许我们创建独立的 DOM 树,它与主文档 DOM 树完全隔离,且具备自己的作用域和 CSS 样式。

创建 Shadow DOM

在 Custom Elements 的构造函数中,我们可以使用 this.attachShadow() 方法创建 Shadow DOM。该方法接受一个配置对象,用于指定 Shadow DOM 的特性。

class MyElement extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' });
    // 在 shadow root 上添加元素和样式
  }
}

在上述代码中,我们使用 this.attachShadow() 方法创建了一个开放式的 Shadow DOM。然后,我们可以在 Shadow DOM 上添加元素和样式,例如:

class MyElement extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
          padding: 10px;
          border: 1px solid black;
        }
        p {
          font-weight: bold;
          color: blue;
        }
      </style>
      <p>Hello, World!</p>
    `;
  }
}

在上述代码中,我们使用 innerHTML 属性向 Shadow DOM 插入了一个样式和一个段落元素,并设置了它们的样式。

将样式从主文档中隔离

使用 Shadow DOM 后,我们可以将样式从主文档中隔离,实现样式的复用和封装。为了做到这一点,我们可以使用 :host 选择器。

:host {
  display: block;
  padding: 10px;
  border: 1px solid black;
}

在上述代码中,我们使用 :host 选择器选择 Shadow DOM 的根元素,然后为其设置样式。这样,我们就可以实现元素与主文档样式的完全隔离。

利用 Custom Elements 和 Shadow DOM 构建可复用的 UI 组件

使用 Custom Elements 和 Shadow DOM,我们可以构建可复用且具有封装性的 UI 组件。下面,我们将使用这两个 API 来创建一个自定义的按钮组件。

定义按钮组件

class MyButton extends HTMLElement {
  constructor() {
    super();

    const shadowRoot = this.attachShadow({ mode: 'open' });

    const style = document.createElement('style');
    style.innerHTML = `
      :host {
        display: inline-block;
        border: none;
        cursor: pointer;
        user-select: none;
        background-color: #007bff;
        color: #fff;
        font-size: 14px;
        padding: 10px 20px;
        outline: none;
        border-radius: 4px;
      }
      :host(:hover) {
        background-color: #0069d9;
      }
    `;

    const button = document.createElement('button');
    button.innerText = this.getAttribute('text');

    shadowRoot.appendChild(style);
    shadowRoot.appendChild(button);
  }
}

customElements.define('my-button', MyButton);

在上述代码中,我们定义了一个名为 MyButton 的自定义元素类。在构造函数中,我们创建了一个 Shadow DOM,并向其中插入了一个样式和一个按钮元素。除此之外,我们还通过 this.getAttribute() 方法获取了自定义元素的属性值,并将它赋值给了按钮的文本。

使用按钮组件

使用按钮组件非常简单,只需要在 HTML 中引用即可。

<my-button text="Click me!"></my-button>

在上述代码中,我们创建了一个名为 my-button 的自定义元素,并将 text 属性设置为 Click me!。这样就创建了一个带有文本的自定义按钮元素。

总结

Custom Elements 和 Shadow DOM API 可以帮助我们实现可复用、封装的 UI 组件。通过继承 HTMLElement 类并使用 attachShadow() 方法创建 Shadow DOM,我们可以实现组件与主文档完全隔离,并拥有自己的 CSS 样式。同时,通过 Custom Elements API,我们还可以像使用普通 HTML 元素一样使用自定义组件,大大提高了组件的可复用性和维护成本。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a47766add4f0e0ffcbe639


纠错反馈