17

現在、StencilJS を使っていくつかの Web コンポーネントを作成しようとしています。

<slot />これで、名前付きスロットとそのすべてが存在することがわかりました。React から来ているので、slot は React の子に似ていると思います。React では子を使用して多くのことができます。私がよくしたこと:

  1. 子供がいるかどうかを確認する
  2. 子を繰り返し処理して、各子に何かを行います (たとえば、クラスを含む div でラップします)。

slot/web components/stencilJS を使用してそれを行うにはどうすればよいでしょうか?

Stencil を使用して、Web コンポーネントのホスト要素を取得できます。

@Element() hostElement: HTMLElement;

私は自分のコンポーネントを次のように使用します

<my-custom-component>
  <button>1</button>
  <button>2</button>
  <button>3</button>
</my-custom-component>

次のようなものをレンダリングしたい

render() {
  return slottedChildren ?
    <span>No Elements</span> :
    <ul class="my-custom-component">
      slottedChildren.map(child => <li class="my-custom-element>{child}</li>)
    </ul>;
}

敬具

4

2 に答える 2

5

ギル様 ご回答ありがとうございます。

私は以前に似たようなことを考えていました(状態の設定など-タイミングの問題が発生する可能性があるため)。コンポーネントがロードされた直後に別のロードをトリガーする componentDidLoad 内で状態変更を行っているためです。これは汚れていてパフォーマンスが悪いようです。

少しでもinnerHTML={child.outerHTML}私を大いに助けてくれました。

あなたも簡単にできるようです:

import {Component, Element, State} from '@stencil/core';

@Component({
    tag: 'slotted-element',
    styleUrl: 'slotted-element.css',
    shadow: true
})
export class SlottedElement {
    @Element() host: HTMLDivElement;

    render() {
        return (
            <div>
                <ul>
                    {Array.from(this.host.children)
                          .map(child => <li innerHTML={child.outerHTML} />)}
                </ul>
            </div>
        );
    }
}

タイミングの問題が発生する可能性があると思いました。これは、ホストの子要素が返さrender()れたときにスペースを確保するために既に削除されているためです。render()しかし、シャドウ DOM とライト DOM はホスト コンポーネント内でうまく共存しているので、問題はないはずです。

なぜあなたが使わなければならないのか、私にはよくわかりませんinnerHTML。私が慣れているReactから来ています:

{Array.from(this.host.children)
      .map(child => <li>{child}</li>)}

そして、それが基本的な JSX 構文であり、Stencil も JSX を使用しているので、それも可能であると考えました。しかし、うまくいきません。innerHTML私のためにトリックを行います。再度、感謝します。

編集: ただし、shadow-dom を使用していない場合は、前述のタイミングの問題が発生します。いくつかの奇妙なことが起こり始め、多くの重複した子供ができてしまいます。あなたはできますが(副作用があるかもしれません):

import {Component, Element, State} from '@stencil/core';

@Component({
    tag: 'slotted-element',
    styleUrl: 'slotted-element.css',
    shadow: true
})
export class SlottedElement {
    children: Element[];

    @Element() host: HTMLDivElement;

    componentWillLoad() {
      this.children = Array.from(this.host.children);
      this.host.innerHTML = '';
    }

    render() {
        return (
            <div>
                <ul>
                    {this.children.map(child => <li innerHTML={child.outerHTML} />)}
                </ul>
            </div>
        );
    }
}
于 2018-09-21T14:33:46.990 に答える