Sch*_*enn 6 web-component stenciljs stencil-component
我目前正在尝试使用StencilJS来创建一些Web组件.
现在我知道有<slot />和名称插槽和所有东西.来自React,我猜插槽与React中的儿童类似.你可以在React中使用孩子做很多事情.我经常做的事情:
你会如何使用插槽/网络组件/ stencilJS?
我可以使用Stencil获取我的Web组件的主机元素
@Element() hostElement: HTMLElement;
Run Code Online (Sandbox Code Playgroud)
我使用我的组件
<my-custom-component>
<button>1</button>
<button>2</button>
<button>3</button>
</my-custom-component>
Run Code Online (Sandbox Code Playgroud)
我想渲染类似的东西
render() {
return slottedChildren ?
<span>No Elements</span> :
<ul class="my-custom-component">
slottedChildren.map(child => <li class="my-custom-element>{child}</li>)
</ul>;
}
Run Code Online (Sandbox Code Playgroud)
亲切的问候
Gil*_*ink 11
使用插槽您不需要在渲染功能中添加条件.你可以在插槽元素中放入no children元素(在你的例子中是span),如果没有为插槽提供子节点,它将回退到它.例如:
render() {
return (
<div>
<slot><span>no elements</span></slot>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
回答你写的评论 - 你可以做这样的事情,但有一些编码,而不是开箱即用.每个槽元素都有一个assignedNodes功能.使用该知识和对Stencil组件生命周期的理解,您可以执行以下操作:
import {Component, Element, State} from '@stencil/core';
@Component({
tag: 'slotted-element',
styleUrl: 'slotted-element.css',
shadow: true
})
export class SlottedElement {
@Element() host: HTMLDivElement;
@State() children: Array<any> = [];
componentWillLoad() {
let slotted = this.host.shadowRoot.querySelector('slot') as HTMLSlotElement;
this.children = slotted.assignedNodes().filter((node) => { return node.nodeName !== '#text'; });
}
render() {
return (
<div>
<slot />
<ul>
{this.children.map(child => { return <li innerHTML={child.outerHTML}></li>; })}
</ul>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
这不是最佳解决方案,它将要求插槽的样式应将显示设置为无(因为您不想显示它).此外,它只适用于只需要渲染而不需要事件或其他任何东西的简单元素(因为它只将它们用作html字符串而不是对象).
谢谢吉尔的回答。
我之前在考虑类似的事情(设置状态等 - 因为可能出现时间问题)。但我不喜欢这个解决方案,因为您随后在 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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
我认为您可能会遇到计时问题,因为在render()主机的子元素期间已经被删除,以便为任何render()返回腾出空间。但由于 Shadow-dom 和 light-dom 在主机组件中很好地共存,我想应该不会有任何问题。
我真的不知道为什么你必须使用innerHTML。来自 React 我习惯这样做:
{Array.from(this.host.children)
.map(child => <li>{child}</li>)}
Run Code Online (Sandbox Code Playgroud)
我认为这是基本的 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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2836 次 |
| 最近记录: |