>  기사  >  웹 프론트엔드  >  사용자 정의 태그와 Shadow DOM으로 HTML 향상

사용자 정의 태그와 Shadow DOM으로 HTML 향상

WBOY
WBOY원래의
2023-08-29 09:37:071072검색

使用自定义标签和 Shadow DOM 增强 HTML

이전 글에서는 맞춤 라벨 제작의 기본 사항을 설명했습니다. 실제로 사용자 정의 태그는 훌륭한 웹 애플리케이션을 구축할 때 취약성을 일부 제거합니다. 그러나 제어 추구는 멈추지 않으며 기존의 사용자 정의 태그로는 성능이 풍부한 애플리케이션을 구축하는 데 충분하지 않습니다. 예를 들어, 사용자 정의 태그를 추가하면 코드의 스타일 선택기 수가 늘어날 수 있습니다. 이는 성능 문제를 일으킬 수 있는 많은 요인 중 하나일 뿐입니다.

이 문제를 해결하는 한 가지 방법은 Shadow DOM을 이용하는 것입니다.

Shadow DOM은 범위가 지정된 스타일을 도입하여 작동합니다. 특별한 명명 규칙이나 도구가 필요하지 않습니다. Shadow DOM을 사용하면 CSS와 마크업을 쉽게 묶을 수 있습니다. 게다가 이 기능을 사용하면 일반 JavaScript 구현에 대한 모든 세부 정보를 숨길 수 있습니다.

Shadow DOM을 사용하는 이유는 무엇인가요?

Shadow DOM은 다음 솔루션을 제공합니다:

  • DOM에서 독립 요소를 허용합니다. document.querySelector와 같은 쿼리는 고아 요소를 반환하지 않습니다.
  • 범위가 지정된 CSS를 허용합니다. 범위가 지정된 CSS는 모든 스타일 규칙이 페이지 내에 유지되도록 합니다. 이는 또한 이름 충돌과 많은 공통 클래스가 없는 더 간단한 CSS 선택기를 의미합니다.

우리의 예

Shadow DOM을 시연하기 위해 tuts-tabs라는 간단한 구성 요소를 사용하겠습니다. 이 문서의 모든 참조는 이 코드를 가리킵니다. Shadow DOM을 사용해 보려면 아래 데모를 살펴보세요.

Shadow DOM 이해

Shadow DOM이란 무엇인가요?

Shadow DOM으로 코딩을 시작하기 전에 일반 DOM을 이해해야 합니다.

HTML은 웹사이트의 중추입니다. 단 몇 분만에 페이지를 만들 수 있습니다. 브라우저에서 페이지를 열면 DOM이 작동합니다. 브라우저가 페이지를 로드하면 HTML을 데이터 모델로 구문 분석하기 시작합니다. 데이터 모델은 노드가 HTML의 요소를 나타내는 트리 구조입니다. 데이터 모델은 코드를 사용하여 쉽게 수정하고 조작할 수 있습니다.

단점은 전체 웹 페이지 또는 복잡한 웹 애플리케이션도 단일 데이터 구조로 취급된다는 것입니다. 디버깅하기 쉽지 않습니다! 예를 들어, 한 구성 요소에 적용된 CSS 스타일은 결국 애플리케이션의 다른 곳에 있는 다른 구성 요소에 영향을 미칠 수 있습니다.

인터페이스의 일부를 나머지 부분과 분리하려면 iframe를 사용하세요. 그러나 iframe은 무겁고 매우 제한적입니다.

이것이 Shadow DOM이 도입된 이유입니다. 이는 웹 개발자가 DOM에 다양한 요소의 하위 트리를 포함할 수 있도록 하는 최신 브라우저의 강력한 기능입니다. DOM의 이러한 하위 트리는 기본 문서 트리에 영향을 주지 않습니다. 기술적으로는 Shadow Trees라고 합니다.

섀도우 트리에는 DOM의 상위 트리에 연결된 섀도우 루트가 있습니다. 이 부모를 Shadow Host라고 합니다.

예를 들어 <input type="range">를 WebKit 기반 브라우저에 연결하면 슬라이더로 변환됩니다. 왜? 하위 트리 DOM 요소 중 하나가 "범위"를 이해하여 모양을 변경하고 슬라이더와 유사한 기능을 도입하기 때문에 이것이 슬라이더입니다. 이는 Shadow DOM이 탭에 제공하는 이점입니다.

와, 이론이 많네요. 이제 Shadow DOM이 어떻게 구현되는지 확인하기 위해 일부 코드를 작성하고 싶을 수도 있습니다.

Shadow DOM 사용에 대한 단계별 가이드

1단계: Shadow DOM 요소 생성

Shadow DOM 요소를 생성하려면 element.attachShadow()를 사용하세요.

이 예에서는 tuts-tab Shadow DOM 요소를 생성하는 데 사용되는 코드를 볼 수 있습니다.

으아악

2단계. Shadow Root에 콘텐츠 추가

다음으로 .innerHTML를 사용하여 섀도우 루트에 콘텐츠를 추가하겠습니다. 이것이 Shadow DOM을 채우는 유일한 방법은 아닙니다. Shadow DOM을 채우는 데 도움이 되는 많은 API가 있습니다.

으아악

3단계: 사용자 정의 요소를 Shadow DOM에 연결

사용자 정의 요소를 Shadow DOM에 연결하는 것은 매우 쉽습니다. 사용자 정의 요소를 Shadow DOM과 결합하면 CSS, JavaScript 및 HTML을 사용하여 캡슐화된 구성 요소를 만들 수 있다는 점을 명심하세요. 따라서 애플리케이션에서 재사용할 수 있는 완전히 새로운 웹 구성 요소를 생성하게 됩니다.

이 예에서는 customElements.define()을 사용하여 새 맞춤 요소를 만듭니다. 이전 튜토리얼에서 언급했듯이 새 요소의 이름에는 "-"가 포함되어야 합니다. customElements.define() 创建一个新的自定义元素。正如上一教程中提到的,新元素的名称中应包含“-”。 tuts-tabs 组件扩展了 HTMLElement 구성 요소는 HTMLElement를 확장합니다.

当我们扩展 HTMLElement 时,在构造函数中调用 super() 非常重要。另外,构造函数是需要创建 shadowRoot 的地方。

customElements.define('tuts-tabs', class extends HTMLElement {
    constructor() {
    super(); // always call super() first in the constructor.

    // Attach a shadow root to <tuts-tabs>.
    const shadowRoot = this.attachShadow({mode: 'open'});
    ...
});

创建 shadowRoot 后,您可以为其创建 CSS 规则。 CSS 规则可以包含在 <style></style> 标记中,并且这些样式的范围仅限于 tuts-tab

customElements.define('tuts-tabs', class extends HTMLElement {
    constructor() {
    super(); 
    const shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = `
         <!-- styles are scoped to tuts-tabs! -->
         <style>#tabs { ... }</style>
    `;
    }
    ...
});

第 4 步:向 Shadow DOM 添加样式

tuts-tab相关的CSS可以写在<style></style>标签内。请记住,此处声明的所有样式都将作用于 tuts-tab Web 组件。 作用域 CSS 是 Shadow DOM 的一项有用功能,它具有以下属性:

  • CSS 选择器不会影响 Shadow DOM 之外的组件。
  • Shadow DOM 中的元素不受其外部选择器的影响。
  • 样式的范围仅限于宿主元素。

如果你想在 Shadow DOM 中选择自定义元素,你可以使用 :host 伪类。当 :host 伪类用于普通 DOM 结构时,它不会产生任何影响。但在 Shadow DOM 内部,它会产生很大的差异。您将在 tuts-tab 组件中找到以下 :host 样式。它决定显示和字体样式。这只是一个简单的示例,展示如何将 :host 合并到 Shadow DOM 中。

:host 的一个问题是它的特殊性。如果父页面有 :host,它将具有更高的特异性。父样式内的所有样式都会获胜。这是从外部覆盖自定义元素内部样式的一种方法。

 :host {
  display: inline-block;
  width: 650px;
  font-family: 'Roboto Slab';
  contain: content;
}

随着 CSS 变得更简单,Shadow DOM 的整体效率也会提高。

下面定义的所有样式都是影子根的本地样式。

shadowRoot.innerHTML = `
<style>
:host {
  display: inline-block;
  width: 650px;
  font-family: 'Roboto Slab';
  contain: content;
}
#panels {
  box-shadow: 0 2px 2px rgba(0, 0, 0, .3);
  background: white;
  border-radius: 3px;
  padding: 16px;
  height: 250px;
  overflow: auto;
}
#tabs slot {
  display: inline-flex; /* Safari bug. Treats <slot> as a parent */
}
...
</style>

同样,您可以自由地在 Shadow DOM 中引入样式表。当您在 Shadow DOM 内链接样式表时,它们的作用域将位于 Shadow 树内。这是一个简单的例子来帮助您理解这个概念。

shadowRoot.innerHTML = `
<style>
:host {
  display: inline-block;
  width: 650px;
  font-family: 'Roboto Slab';
  contain: content;
}
#panels {
  box-shadow: 0 2px 2px rgba(0, 0, 0, .3);
  background: white;
  border-radius: 3px;
  padding: 16px;
  height: 250px;
  overflow: auto;
}
...
</style>
<link rel="stylesheet" href="styles.css">
...

步骤 5. 在自定义组件中定义 HTML 元素

接下来,我们可以定义 tuts-tab 的 HTML 元素。

在简单的选项卡结构中,应该有可单击的标题和反映所选标题内容的面板。这显然意味着我们的自定义元素应该有一个带有标题的 div 和一个用于面板的 div 。 HTML 组件将定义如下:

customElements.define('tuts-tabs', class extends HTMLElement {
    constructor() {
    super(); const shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = `
        <style>#tabs { ... }</style>
        
        ....
        
        // Our HTML elements for tuts-tab
        <div id="tabs">...</div>
        <div id="panels">...</div>
        ...
    `;
    }
    ...
});

在面板的 div 中,您会遇到一个有趣的标签,名为 <slot></slot>。我们的下一步是了解有关插槽的更多信息。

第 6 步:在 Shadow DOM 中使用槽

Slot 在 Shadow DOM API 中起着至关重要的作用。插槽充当自定义组件内的占位符。这些组件可以由您自己的标记填充。槽声明分为三种不同类型:

  1. 您可以拥有零个插槽的组件。
  2. 您可以创建一个包含后备内容或空内容的槽位。
  3. 您可以使用整个 DOM 树创建槽。

在我们的 tuts-tabs 中,我们有一个用于选项卡标题的命名槽,以及另一个用于面板的槽。命名槽会创建您可以通过名称引用的孔。

customElements.define('tuts-tabs', class extends HTMLElement {
    constructor() {
    super(); const shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = `
        <style>#tabs { ... }</style>
        
        ....
        
        // Our HTML elements for tuts-tab
        <div id="tabs">
            <slot id="tabsSlot" name="title"></slot>
         </div>
        <div id="panels">
            <slot id="panelsSlot"></slot>
        </div>
        ...
    `;
    }
    ...
});

第 7 步:填充插槽

现在,是时候填充插槽了。在之前的教程中,我们了解了定义自定义元素的四种不同方法,并且 tuts-tabs 使用其中两种方法来构建选项卡:connectedCallbackdisconnectedCallback

connectedCallback 中,我们将填充步骤 6 中定义的槽。我们的 connectedCallback 将定义如下。我们使用 querySelector 来识别 tabsSlotpanelsSlot。当然,这并不是识别 HTML 中插槽的唯一方法。

识别槽后,您需要为其分配节点。在 tuts-tab 中,我们使用以下 tabsSlot.assignedNodes 来标识选项卡的数量。

connectedCallback() {
    ...
    const tabsSlot = this.shadowRoot.querySelector('#tabsSlot');
    const panelsSlot = this.shadowRoot.querySelector('#panelsSlot');

    this.tabs = tabsSlot.assignedNodes({flatten: true});
    this.panels = panelsSlot.assignedNodes({flatten: true}).filter(el => {
      return el.nodeType === Node.ELEMENT_NODE;
    });
    ...
  }

此外,connectedCallback 是我们注册所有事件监听器的地方。每当用户单击选项卡标题时,面板的内容都需要更改。可以在 connectedCallback 函数中注册用于实现此目的的事件侦听器。

第 8 步:实现逻辑和交互性

我们不会深入探讨如何实现选项卡及其功能的逻辑。但是,请记住,我们的自定义 tuts-tab 组件中实现了以下方法,用于在选项卡之间切换:

  1. onTitleClick 该方法捕获选项卡标题上的点击事件。它有助于在选项卡面板内切换内容。
  2. selectTab该函数负责隐藏面板和显示右侧面板。此外,它还负责突出显示所选的选项卡。
  3. findFirstSelected此方法用于在第一次加载时选择选项卡。
  4. selected这是一个用于获取所选选项卡的 getter 和 setter。

第 9 步.定义生命周期方法

继续,不要忘记定义 disconnectedCallback。这是自定义元素中的生命周期方法。当自定义元素从视图中销毁时,会触发此回调。这是在应用程序中删除操作侦听器和重置控件的最佳位置之一。但是,回调的范围仅限于自定义元素。在我们的例子中,它将是 tuts-tab

第 10 步。使用新组件!

最后一步是在 HTML 中使用 tuts-tab 。我们可以很容易地在 HTML 标记中插入 tuts-tab 。这是一个简单的例子来演示其用法。

<tuts-tabs background>
  <button slot="title">Tab 1</button>
  <button slot="title" selected>Tab 2</button>
  <button slot="title">Tab 3</button>
  <section>content panel 1</section>
  <section>content panel 2</section>
  <section>content panel 3</section>
</tuts-tabs>

结论

我们开始了!我们已经完成了一个重要教程,在该教程中我们创建并使用了自定义元素。该过程很简单,并且在开发网页时被证明非常有用。我希望您尝试创建自定义元素并与我们分享您的经验。

위 내용은 사용자 정의 태그와 Shadow DOM으로 HTML 향상의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.