Heim  >  Artikel  >  Web-Frontend  >  Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

不言
不言nach vorne
2018-10-18 13:58:177384Durchsuche

Der Inhalt dieses Artikels dreht sich um: Wissen Sie, was eine native HTML-Komponente ist? Die Einführung nativer HTML-Komponenten hat einen gewissen Referenzwert. Ich hoffe, dass es für Sie hilfreich ist.

Hey! Schauen Sie sich die letzten Jahre an, die Entwicklung des Web-Frontends ist so schnell!

Vor ein paar Jahren war HTML eine grundlegende Fähigkeit für Frontend-Entwickler. Eine benutzerfreundliche Website konnte über verschiedene Tags erstellt werden, und grundlegende Interaktion war kein Problem. Wenn Sie etwas mehr CSS haben, ist es goldbraun, knusprig und köstlich. Das Hinzufügen einiger weiterer JavaScripts zu diesem Zeitpunkt macht einfach süchtig.

Mit zunehmender Nachfrage wird die Struktur von HTML immer komplexer. Eine große Anzahl wiederholter Codes macht es extrem schwierig, die Seite zu ändern. Dies hat auch eine Reihe von Vorlagentools zum Extrahieren hervorgebracht Gemeinsame Teile in öffentliche Komponenten umwandeln. Später, mit Leistungsverbesserungen für JavaScript, JavaScript Sein Status wird immer höher und es ist nicht mehr nur eine Beilage. Das Aufkommen des Front-End-Renderings hat den Druck auf den Server verringert, Vorlagen zu analysieren. Der Server muss nur statische Dateien und APIs bereitstellen. Nur die Schnittstelle reicht aus. Dann wurden die Front-End-Rendering-Tools zurück auf den Server verschoben und das Back-End-Rendering erschien (schwarzes Fragezeichen???)

Kurz gesagt, die Komponentisierung macht die komplexe Front-End-Struktur klar und verdeutlicht sie Teileunabhängigkeit. Hohe Kohäsion und geringe Kopplung reduzieren die Wartungskosten erheblich.

Haben Sie schon von nativen HTML-Komponenten gehört?

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Vier wichtige Standards für Webkomponenten

Bevor wir über native HTML-Komponenten sprechen, müssen wir Folgendes nennen: Kurze Einführung Die vier wichtigsten Standards für Webkomponenten sind: HTML Vorlage, Shadow DOM, benutzerdefinierte Elemente und HTML Importe. Tatsächlich wurde einer von ihnen aufgegeben, sodass daraus die „Großen Drei“ wurden.

HTML-Vorlage Ich glaube, viele Leute haben davon gehört. Unter normalen Umständen ist es farblos und geruchlos, und seine Existenz ist nicht einmal wahrnehmbar img darunter wird weder heruntergeladen, noch wird das Skript ausgeführt.

Shadow DOM ist ein grundlegendes Tool für die native Komponentenkapselung, mit dem Unabhängigkeit zwischen Komponenten erreicht werden kann.

Custom Elements ist ein Container, der zum Verpacken nativer Komponenten verwendet wird. Sie müssen lediglich ein Tag schreiben, um eine vollständige Komponente zu erhalten.

HTML Importe ähneln dem ES6-Modul in HTML. Sie können eine andere HTML-Datei direkt importieren und dann verwenden. DOM-Knoten. Da HTML-Importe und ES6-Module jedoch so ähnlich sind, mit Ausnahme von Chrome Kein anderer Browser ist bereit, es zu implementieren, daher ist es veraltet und wird nicht empfohlen. In Zukunft wird es durch das ES6-Modul ersetzt, es scheint jedoch noch keinen Ersatzplan für die neue Version zu geben Diese Funktion wurde in Chrome entfernt und bei Verwendung wird in der Konsole eine Warnung angezeigt. Die Warnung besagt, dass stattdessen ES-Module verwendet werden sollen, aber als ich es getestet habe Das ES-Modul in Chrome 71 erzwingt, dass der MIME-Typ der erkannten Datei ein JavaScript-Typ ist, der möglicherweise noch nicht unterstützt wird.

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Shadow DOM

Um über native HTML-Komponenten zu sprechen, müssen wir zuerst darüber sprechen, was Shadow DOM ist ist etwas.

Jeder kennt DOM. Es existiert als das grundlegendste Grundgerüst in HTML. Es ist eine Baumstruktur und jeder Knoten im Baum ist Teil von HTML. Als Baum hat DOM eine hierarchische Beziehung zwischen oberen und unteren Ebenen. Wir verwenden normalerweise „übergeordneter Knoten“, „untergeordneter Knoten“, „geschwisterlicher Knoten“ usw., um es zu beschreiben (natürlich denken einige Leute, dass diese Begriffe das Geschlecht betonen). deshalb schaffen sie auch einige geschlechtsneutrale Titel). Untergeordnete Knoten erben bis zu einem gewissen Grad einige Dinge vom übergeordneten Knoten und haben auch bestimmte Auswirkungen von Geschwisterknoten. Das Offensichtlichste ist, dass der untergeordnete Knoten bei der Anwendung des CSS-Stils einige Stile vom übergeordneten Knoten erbt.

Und Shadow DOM ist auch eine Art von DOM, also ist es auch ein Baum, außer dass es sich um eine spezielle lila Süßkartoffel handelt, die auf dem DOM-Baum wächst, ach nein, ein Unterbaum.

Was? Besteht das DOM selbst nicht nacheinander aus Teilbäumen? Gibt es etwas Besonderes an diesem Shadow DOM?

Das Besondere an Shadow DOM ist, dass es darauf abzielt, einen relativ unabhängigen Raum zu schaffen. Obwohl es auch auf dem DOM-Baum wächst, ist seine Umgebung natürlich von der Außenwelt isoliert In diesem isolierten Bereich können Sie selektiv einige Eigenschaften vom übergeordneten Knoten im DOM-Baum erben oder sogar einen DOM-Baum erben.

Mithilfe der Isolation von Shadow DOM können wir native HTML-Komponenten erstellen.

Tatsächlich hat der Browser bereits einige Komponenten über Shadow DOM implementiert, aber wir haben sie verwendet, ohne es zu merken. Das ist auch der Charme der von Shadow DOM gekapselten Komponenten: Sie schreiben einfach ein HTML-Tag und überlassen den Rest Mich. . (Ist es nicht ein bisschen wie JSX von React?)

Werfen wir einen Blick auf ein Beispiel, das vom Browser mithilfe von Shadow DOM implementiert wurde, nämlich das Video-Tag:

<video></video>

Werfen wir einen Blick darauf beim Durchsuchen Das Ergebnis des Renderer-Renderings:

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Warten Sie eine Minute! Meinst du nicht Shadow DOM? Wie unterscheidet sich das von einem normalen DOM? ? ?

In Chrome zeigt Elements den intern implementierten Shadow-DOM-Knoten standardmäßig nicht an und muss in den Einstellungen aktiviert werden:

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Hinweis: Der Browser verbirgt standardmäßig seine eigene Shadow-DOM-Implementierung. Wenn das Shadow-DOM jedoch vom Benutzer über ein Skript erstellt wird, wird es nicht ausgeblendet.

Dann können wir das wahre Gesicht des Video-Tags sehen:

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Hier können Sie es nach Belieben anpassen, genau wie beim Debuggen eines normalen Tags DOM Der Inhalt im Schatten-DOM (jedenfalls ist er derselbe wie im normalen DOM und wird nach der Aktualisierung wiederhergestellt).

Wir können sehen, dass die meisten Knoten im Schatten-DOM oben Pseudoattribute haben. Gemäß diesem Attribut können Sie CSS-Stile außerhalb schreiben, um die entsprechenden Knotenstile zu steuern. Ändern Sie beispielsweise die Hintergrundfarbe der Eingabeschaltfläche über pseudo="-webkit-media-controls-overlay-play-button" in Orange:

video::-webkit-media-controls-overlay-play-button {
  background-color: orange;
}

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Da es sich bei Shadow DOM tatsächlich um eine Art DOM handelt, können Sie Shadow DOM wie oben beschrieben weiterhin im Shadow DOM verschachteln.

Es gibt viele Elemente im Browser, die in Form von Shadow DOM gekapselt sind, wie z. B. ,

Aufgrund der Isolation von Shadow DOM wird das div innerhalb von Shadow DOM in keiner Weise beeinflusst, selbst wenn Sie einen Stil außerhalb von div { background-color: red !important; schreiben

Mit anderen Worten: Verwenden Sie beim Schreiben von Stilen id, wenn Sie id verwenden sollten, und verwenden Sie class, wenn Sie class verwenden sollten. Wenn die Klasse einer Schaltfläche als .button geschrieben werden soll, dann sollte sie als .button geschrieben werden. Es besteht keine Notwendigkeit zu berücksichtigen, dass die ID und die Klasse in der aktuellen Komponente möglicherweise mit anderen Komponenten in Konflikt stehen. Sie müssen lediglich sicherstellen, dass es innerhalb einer Komponente keinen Konflikt gibt – dies ist einfach.

Dies löst das Problem, mit dem die meisten komponentenbasierten Frameworks heutzutage konfrontiert sind: Wie schreibe ich die Klasse (Klassenname) von Element? Die Verwendung eines vorangestellten Namespace führt zu einem zu langen Klassennamen, wie zum Beispiel diesem: .header-nav-list-sublist-button-icon; Mit einigen CSS-in-JS-Tools können Sie einige eindeutige Klassennamen erstellen, wie zum Beispiel diesen : .Nav__welcomeWrapper___lKXTg, dieser Name ist noch etwas lang und enthält redundante Informationen.

ShadowRoot

ShadowRoot ist die Wurzel unter Shadow DOM. Sie können es wie

behandeln, aber es ist nicht Einige Eigenschaften von können nicht verwendet werden, obwohl es sich nicht um einen Knoten handelt.

Sie können den gesamten Shadow-DOM-Baum über Attribute oder Methoden wie appendChild und querySelectorAll unter ShadowRoot bedienen.

Für ein gewöhnliches Element wie

können Sie eine ShadowRoot erstellen, indem Sie die Methode attachmentShadow darauf aufrufen (es gibt auch eine Methode createShadowRoot, die veraltet ist und nicht empfohlen wird, ein Objekt zu akzeptieren). . Initialisierung: { mode: 'open' }, dieses Objekt hat ein Modusattribut mit zwei Werten: 'open' und 'closed'. Dieses Attribut muss beim Erstellen von ShadowRoot initialisiert werden und wird nach dem Erstellen schreibgeschützt Eigentum.

mode: 'open' 和 mode: 'closed' 有什么区别呢?在调用 attachShadow 创建 ShadowRoot 之后,attachShdow 方法会返回 ShadowRoot 对象实例,你可以通过这个返回值去构造整个 Shadow DOM。当 mode 为 'open' 时,在用于创建 ShadowRoot 的外部普通节点(比如

)上,会有一个 shadowRoot 属性,这个属性也就是创造出来的那个 ShadowRoot,也就是说,在创建 ShadowRoot 之后,还是可以在任何地方通过这个属性再得到 ShadowRoot,继续对其进行改造;而当 mode 为 'closed' 时,你将不能再得到这个属性,这个属性会被设置为 null,也就是说,你只能在 attachShadow 之后得到 ShadowRoot 对象,用于构造整个 Shadow DOM,一旦你失去对这个对象的引用,你就无法再对 Shadow DOM 进行改造了。

可以从上面 Shadow DOM 的截图中看到 #shadow-root (user-agent) 的字样,这就是 ShadowRoot 对象了,而括号中的 user-agent 表示这是浏览器内部实现的 Shadow DOM,如果使用通过脚本自己创建的 ShadowRoot,括号中会显示为 open 或 closed 表示 Shadow DOM 的 mode。

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

浏览器内部实现的 user-agent 的 mode 为 closed,所以你不能通过节点的 ShadowRoot 属性去获得其 ShadowRoot 对象,也就意味着你不能通过脚本对这些浏览器内部实现的 Shadow DOM 进行改造。

HTML Template

有了 ShadowRoot 对象,我们可以通过代码来创建内部结构了,对于简单的结构,也许我们可以直接通过 document.createElement 来创建,但是稍微复杂一些的结构,如果全部都这样来创建不仅麻烦,而且代码可读性也很差。当然也可以通过 ES6 提供的反引号字符串(const template = `......`;)配合 innerHTML 来构造结构,利用反引号字符串中可以任意换行,并且 HTML 对缩进并不敏感的特性来实现模版,但是这样也是不够优雅,毕竟代码里大段大段的 HTML 字符串并不美观,即便是单独抽出一个常量文件也是一样。

这个时候就可以请 HTML Template 出场了。我们可以在 html 文档中编写 DOM 结构,然后在 ShadowRoot 中加载过来即可。

HTML Template 实际上就是在 html 中的一个

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

通过 document-fragment 对象,就可以访问到 template 内部的节点了,通过 document.importNode 方法,可以将 document-fragment 对象创建一份副本,然后可以使用一切 DOM 属性方法替换副本中的模版内容,最终将其插入到 DOM 或是 Shadow DOM 中。

<div></div>
<template>
  <div></div>
</template>
const template = document.getElementById('temp');
const copy = document.importNode(template.content, true);
copy.getElementById('title').innerHTML = 'Hello World!';

const div = document.getElementById('div');
const shadowRoot = div.attachShadow({ mode: 'closed' });
shadowRoot.appendChild(copy);

HTML Imports

有了 HTML Template,我们已经可以方便地创造封闭的 Web 组件了,但是目前还有一些不完美的地方:我们必须要在 html 中定义一大批的

此时,我们就可以用到已经被废弃的 HTML Imports 了。虽然它已经被废弃了,但是未来会通过 ES6 Modules 的形式再进行支持,所以理论上也只是换个加载形式而已。

通过 HTML Imports,我们可以将

已经废弃的 HTML Imports 通过 标签实现,只要指定 rel="import" 就可以了,就像这样:,它可以接受 onload 和 onerror 事件以指示它已经加载完成。当然也可以通过脚本来创建 link 节点,然后指定 rel 和 href 来按需加载。Import 成功后,在 link 节点上有一个 import 属性,这个属性中存储的就是 import 进来的 DOM 树啦,可以 querySelector 之类的,并通过 cloneNode 或 document.importNode 方法创建副本后使用。

未来新的 HTML Imports 将会以 ES6 Module 的形式提供,可以在 JavaScript 中直接 import * as template from './template.html';,也可以按需 import,像这样:const template = await import('./template.html');。不过目前虽然浏览器都已经支持 ES6 Modules,但是在 import 其他模块时会检查服务端返回文件的 MIME 类型必须为 JavaScript 的 MIME 类型,否则不允许加载。

Custom Elements

有了上面的三个组件标准,我们实际上只是对 HTML 进行拆分而已,将一个大的 DOM 树拆成一个个相互隔离的小 DOM 树,这还不是真正的组件。

要实现一个真正的组件,我们就需要用到 Custom Elements 了,就如它的名字一样,它是用来定义原生组件的。

Custom Elements 的核心,实际上就是利用 JavaScript 中的对象继承,去继承 HTML 原生的 HTMLElement 类(或是具体的某个原生 Element 类,比如 HTMLButtonElement),然后自己编写相关的生命周期函数,处理成员属性以及用户交互的事件。

看起来这和现在的 React 很像,在 React 中,你可以这样创造一个组件:class MyElement extends React.Component { ... },而使用原生 Custom Elements,你需要这样写:class MyElement extends HTMLElement { ... }。

Custom Elements 的生命周期函数并不多,但是足够使用。这里我将 Custom Elements 的生命周期函数与 React 进行一个简单的对比:

constructor(): 构造函数,用于初始化 state、创建 Shadow DOM、监听事件之类。

对应 React 中 Mounting 阶段的大半部分,包括:constructor(props)、static getDerivedStateFromProps(props, state) 和 render()。

在 Custom Elements 中,constructor() 构造函数就是其原本的含义:初始化,和 React 的初始化类似,但它没有像 React 中那样将其拆分为多个部分。在这个阶段,组件仅仅是被创建出来(比如通过 document.createElement()),但是还没有插入到 DOM 树中。

connectedCallback(): 组件实例已被插入到 DOM 树中,用于进行一些展示相关的初始化操作。

对应 React 中 Mounting 阶段的最后一个生命周期:componentDidMount()。

在这个阶段,组件已经被插入到 DOM 树中了,或是其本身就在 html 文件中写好在 DOM 树上了,这个阶段一般是进行一些展示相关的初始化,比如加载数据、图片、音频或视频之类并进行展示。

attributeChangedCallback(attrName, oldVal, newVal): 组件属性发生变化,用于更新组件的状态。

对应 React 中的 Updating 阶段:static getDerivedStateFromProps(props, state)、shouldComponentUpdate(nextProps, nextState)、render()、getSnapshotBeforeUpdate(prevProps, prevState) 和 componentDidUpdate(prevProps, prevState, snapshot)。

当组件的属性(React 中的 props)发生变化时触发这个生命周期,但是并不是所有属性变化都会触发,比如组件的 class、style 之类的属性发生变化一般是不会产生特殊交互的,如果所有属性发生变化都触发这个生命周期的话,会使得性能造成较大的影响。所以 Custom Elements 要求开发者提供一个属性列表,只有当属性列表中的属性发生变化时才会触发这个生命周期函数。

这个属性列表通过组件类上的一个静态只读属性来声明,在 ES6 Class 中使用一个 getter 函数来实现,只实现 getter 而不实现 setter,getter 返回一个常量,这样就是只读的了。像这样:

class AwesomeElement extends HTMLElement {
  static get observedAttributes() {
    return [&#39;awesome&#39;];
  }
}

disconnectedCallback(): 组件被从 DOM 树中移除,用于进行一些清理操作。

对应 React 中的 Unmounting 阶段:componentWillUnmount()。

adoptedCallback(): 组件实例从一个文档被移动到另一个文档。

这个生命周期是原生组件独有的,React 中没有类似的生命周期。这个生命周期函数也并不常用到,一般在操作多个 document 的时候会遇到,调用 document.adoptNode() 函数转移节点所属 document 时会触发这个生命周期。

在定义了自定义组件后,我们需要将它注册到 HTML 标签列表中,通过 window.customElements.define() 函数即可实现,这个函数接受两个必须参数和一个可选参数。第一个参数是注册的标签名,为了避免和 HTML 自身的标签冲突,Custom Elements 要求用户自定义的组件名必须至少包含一个短杠 -,并且不能以短杠开头,比如 my-element、awesome-button 之类都是可以的。第二个参数是注册的组件的 class,直接将继承的子类类名传入即可,当然也可以直接写一个匿名类:

window.customElements.define('my-element', class extends HTMLElement {
  ...
});

注册之后,我们就可以使用了,可以直接在 html 文档中写对应的标签,比如:,也可以通过 document.createElement('my-element') 来创建,用法与普通标签几乎完全一样。但要注意的是,虽然 html 标准中说部分标签可以不关闭或是自关闭(
或是
),但是只有规定的少数几个标签允许自关闭,所以,在 html 中写 Custom Elements 的节点时必须带上关闭标签。

由于 Custom Elements 是通过 JavaScript 来定义的,而一般 js 文件都是通过 <script> 标签外联的,所以 html 文档中的 Custom Elements 在 JavaScript 未执行时是处于一个默认的状态,浏览器默认会将其内容直接显示出来。为了避免这样的情况发生,Custom Elements 在被注册后都会有一个 :defined CSS 伪类而在注册前没有,所以我们可以通过 CSS 选择器在 Custom Elements 注册前将其隐藏起来,比如:</script>

my-element:not(:defined) {
  display: none;
}

或者 Custom Elements 也提供了一个函数来检测指定的组件是否已经被注册:customElements.whenDefined(),这个函数接受一个组件名参数,并返回一个 Promise,当 Promise 被 resolve 时,就表示组件被注册了。

这样,我们就可以放心的在加载 Custom Elements 的 JavaScript 的 <script> 标签上使用 async 属性来延迟加载了(当然,如果是使用 ES6 Modules 形式的话默认的加载行为就会和 defer 类似)。</script>

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

Custom Elements + Shadow DOM

使用 Custom Elements 来创建组件时,通常会与 Shadow DOM 进行结合,利用 Shadow DOM 的隔离性,就可以创造独立的组件。

通常在 Custom Elements 的 constructor() 构造函数中去创建 Shadow DOM,并对 Shadow DOM 中的节点添加事件监听、对特定事件触发原生 Events 对象。

正常编写 html 文档时,我们可能会给 Custom Elements 添加一些子节点,像这样:

Title

Content

,而我们创建的 Shadow DOM 又拥有其自己的结构,怎样将这些子节点放置到 Shadow DOM 中正确的位置上呢?

在 React 中,这些子节点被放置在 props 的 children 中,我们可以在 render() 时选择将它放在哪里。而在 Shadow DOM 中有一个特殊的标签:,这个标签的用处就如同其字面意思,在 Shadow DOM 上放置一个“插槽”,然后 Custom Elements 的子节点就会自动放置到这个“插槽”中了。

有时我们需要更加精确地控制子节点在 Shadow DOM 中的位置,而默认情况下,所有子节点都会被放置在同一个 标签下,即便是你写了多个 。那怎样更精确地对子节点进行控制呢?

默认情况下,Fallback 这样的是默认的 ,只有第一个默认的 会有效,将所有子节点全部放进去,如果没有可用的子节点,将会显示默认的 Fallback 内容(Fallback 可以是一棵子 DOM 树)。

标签有一个 name 属性,当你提供 name 后,它将变为一个“有名字的 ”,这样的 可以存在多个,只要名字各不相同。此时他们会自动匹配 Custom Elements 下带 slot 属性并且 slot 属性与自身 name 相同的子节点,像这样

<template>
  <div>
    <h1>Others</h1>
    <slot></slot>
  </div>
  <div>
    <h1>Animals</h1>
    <slot></slot>
  </div>
  <div>
    <h1>Fruits</h1>
    <slot></slot>
  </div>
</template>

<my-list>
  <div>Cat</div>
  <div>Apple</div>
  <div>Banana</div>
  <div>flower</div>
  <div>pencil</div>
  <div>Dog</div>
  <div>peach</div>
  <div>red</div>
</my-list>
class MyList extends HTMLElement {
  constructor() {
    super();
    const root = this.attachShadow({ mode: 'open' });
    const template = document.getElementById('list');
    root.appendChild(document.importNode(template.content, true));
  }
}
customElements.define('my-list', MyList);

这样就可以得到如图所示的结构,#shadow-root (open) 表示这是一个开放的 Shadow DOM,下面的节点是直接从 template 中 clone 过来的,浏览器自动在三个 标签下放置了几个灰色的

节点,实际上这些灰色的
节点表示的是到其真实节点的“引用”,鼠标移动到他们上会显示一个 reveal 链接,点击这个链接即可跳转至其真实节点。

Wissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten

这里我们可以看到,虽然 下的子节点是乱序放置的,但是只要是给定了 slot 属性,就会被放置到正确的 标签下。注意观察其中有一个

flower
,这个节点由于指定了 slot="other",但是却找不到匹配的 标签,所以它不会被显示在结果中。

在为 Custom Elements 下的 Shadow DOM 设置样式的时候,我们可以直接在 Shadow DOM 下放置

在 Shadow DOM 内部的样式中,也有一些特定的选择器,比如 :host 选择器,代表着 ShadowRoot,这类似于普通 DOM 中的 :root,并且它可以与其他伪类组合使用,比如当鼠标在组件上时::host(:hover),当组件拥有某个 class 时::host(.awesome),当组件拥有 disabled 属性时::host([disabled])……但是 :host 是拥有继承属性的,所以如果在 Custom Elements 外部定义了某些样式,将会覆盖 :host 中的样式,这样就可以轻松地实现各式各样的“主题风格”了。

为了实现自定义主题,我们还可以使用 Shadow DOM 提供的 :host-context() 选择器,这个选择器允许检查 Shadow DOM 的任何祖先节点是否包含指定选择器。比如如果在最外层 DOM 的 或

上有一个 class:.night,则 Shadow DOM 内就可以使用 :host-context(.night) 来指定一个夜晚的主题。这样可以实现主题样式的继承。

还有一种样式的定义方式是利用 CSS 变量。我们在 Shadow DOM 中使用变量来指定样式,比如:background-color: var(--bg-colour, #0F0);,这样就可以在 Shadow DOM 外面指定 --bg-colour 变量来设置样式了,如果没有指定变量,将使用默认的样式颜色 #0F0。

有时我们需要在 Shadow DOM 内部使用完全自定义的样式,比如字体样式、字体大小,如果任由其继承可能导致布局错乱,而每次在组件外面指定样式又略显麻烦,并且也破坏了组件的封装性。所以,Shadow DOM 提供了一个 all 属性,只要指定 :host{ all: initial; } 就可以重置所有继承的属性。

Demo

Web Components 的 Demo 在网上已经有很多了,这是我 2 年前初次接触 ES6 与 Web Components 的时候写的一个 Demo:https://github.com/jinliming2/Calendar-js,一个日历,当时还是 v0 的规范,并且在 Firefox 下还存在会导致 Firefox 崩溃的 Bug(感觉是 Firefox 在实现 Shadow DOM 时的 Bug)。目前这个 Demo 已经不能在 Firefox 下运行了,因为 Firefox 已经删除了 v0 规范,开始实行 v1 标准了,所以近期我可能会重构一下这个 Demo。

Das obige ist der detaillierte Inhalt vonWissen Sie, was eine native HTML-Komponente ist? Einführung in native HTML-Komponenten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen