Web components: How to work with children?

后端 未结 2 1530
慢半拍i
慢半拍i 2021-02-13 17:35

I\'m currently experimenting with StencilJS to create some web components.

Now I know that there is and named slots and all that stuff. Comin

2条回答
  •  说谎
    说谎 (楼主)
    2021-02-13 18:07

    Thank you for the answer Gil.

    I was thinking of something similar before (setting state etc. - because of timing issues that might come up). I didn't like the solution though, because you're then doing a state change within componentDidLoad, which will trigger another load just after the component did load. This seems dirty and unperfomant.

    The little bit with innerHTML={child.outerHTML} helped me alot though.

    It seems like you can also simply do:

    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 (
                
      {Array.from(this.host.children) .map(child =>
    • )}
    ); } }

    I thought you might run into timing issues, because during render() the child elements of the host have already been removed to make space for whatever render() returns. But since shadow-dom and light-dom coexist nicely within the host component, I guess there shouldn't be any issues.

    I don't really know why you have to use innerHTML though. Coming from React I'm used to doing:

    {Array.from(this.host.children)
          .map(child => 
  • {child}
  • )}

    And I thought that is basic JSX syntax and that since Stencil is also using JSX I could do that, too. Doesn't work though. innerHTML does the trick for me. Thanks again.

    EDIT: The timing issues I mentioned will appear if you're not using shadow-dom though. Some strange things start to happen an you'll end up with a lot of duplicate children. Though you can do (might have side effects):

    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 (
                
      {this.children.map(child =>
    • )}
    ); } }

提交回复
热议问题