javascript - Använda slots i WebComponents utan att använda shadow DOM


Jag försöker bygga en WebComponent utan att använda ShadowDOM - hittills har det mestadels fungerat, men nu vill jag bygga en komponent som omsluter andra komponenter precis som man skulle göra med Angulars @ViewChild/@ViewChildren. (biblioteket jag använder här för att rendera är uhtml, liknande lit-html)

export class Dropdown extends HTMLElement {

    private open: boolean = false;

    static observedAttributes = ["open"]

    constructor() {
        super();
    }

    attributeChangedCallback(name: string, oldValue: string, newValue: string) {
        switch (name) {
            case "open":
                this.open = Boolean(newValue);
                break;
        }
        this.display()
    }

    connectedCallback() {
        this.display()
    }

    display = () => {
        render(this, html`
            <div>
                <slot name="item">

                </slot>
            </div>
        `)
    }

    static register = () => customElements.define("my-dropdown", Dropdown)

}

Om jag nu använder denna komponent

Dropdown.register();


render(document.body, html`
    <my-dropdown open="true">
        <strong slot="item">test</strong>
    </my-dropdown>

`)

Jag förväntar mig att se

<my-dropdown>
    <div>
        <strong>test</test>
    </div>
</my-dropdown>

men slottdelen fungerar inte.

Om jag byter till ShadowDOM fungerar det bara, men nu måste jag hantera ShadowDOM:s sandlåda när det gäller styling, vilket jag helst inte vill göra.

constructor() {
    super();
    this.attachShadow({mode: "open"})
}
display = () => {
    render(this.shadowRoot as Node, html`

Är det möjligt att få slots att fungera utan shadowDOM? Om inte, finns det ett annat sätt att hämta innehållet som definierats inuti komponenten och använda det i visningen?

<my-component>
    <div>some content here</div>
</my-component>

bör renderas som

<my-component>
    <header>
        random header
    </header>
    <section>
        <!-- my custom content -->
        <div>some content here</div>
    </section>
</my-component>

Några förslag?

Svar #1

Nej, <slot> är en del av shadowDOM API:et

Du kan fejka det, men eftersom det inte finns något shadowDOM skulle du behöva lagra det innehållet någon annanstans.
Det kan vara en <template> som du läser och analyserar ditt (lätta)DOM-innehåll i.

Det där är en j*vla massa DOM-mutationer.
Det kan vara lättare att bara lära sig att styla shadowDOM med:

  • CSS-egenskaper
  • ärvbara stilar
  • ::slotted
  • ::del
  • konstruerbara stilmallar

Relaterade artiklar