如何使用 TSX 使 StencilJS 组件在没有组件标签本身的情况下呈现?
How can I make StencilJS component to render without component tag itself with TSX?
虽然我知道这可能是一种糟糕的做法,但我需要构建 StencilJS 组件,以便在 render() 内部,我不想渲染组件标签本身,因为已经存在样式指南并且它期望 DOM 以某种方式构建。这是我要实现的目标 - 组件代码(来自 HTML 或在另一个组件内):
<tab-header-list>
<tab-header label="tab 1"></tab-header>
<tab-header label="tab 2"></tab-header>
</tab-header-list>
渲染时,我希望生成的 DOM 类似于:
<tab-header-list>
<ul>
<li>tab 1</li>
<li>tab 2</li>
</ul>
</tab-header-list>
所以在 tab-header-list render() 函数中,我正在做
return (
<ul>
<slot/>
</ul>
);
我可以在 tab-header render() 函数中执行此操作
@Element() el: HTMLElement;
@Prop() label: string;
render() {
this.el.outerHTML = `<li>${this.label}</li>`;
}
得到我想要的,但我如何使用 TSX 做到这一点? (为简单起见,上面的代码非常简单,但我真正需要构建的是带有事件等的更复杂的 li 标签,所以我想使用 TSX)
试图将 DOM 存储到变量,但我不确定如何将其分配为 this.el(外部 HTML 似乎是我能想到的唯一方法,但我觉得一定有更好的方法)
@Element() el: HTMLElement;
@Prop() label: string;
render() {
var tabheaderDOM = (<li>{this.label}</li>);
// how can I assign above DOM to this.el somehow?
//this.el.outerHTML = ?
}
非常感谢能得到的任何帮助 - 提前感谢您的宝贵时间!
遗憾的是,您不能使用没有标签的自定义元素,但有一个解决方法:
您可以使用 Host
元素作为结果标签的参考。
render () {
return (
<Host>....</Host>
)
}
然后在你的样式表中你可以为它设置 display
属性:
:host {
display: contents;
}
display: contents causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself
注意:它在 IE、opera mini 中不起作用...https://caniuse.com/#feat=css-display-contents
更新:
如果您不使用 shadowDOM
,则需要将 :host
替换为标签名称,例如:
tab-header {
display: contents;
}
功能组件或许可以帮助您实现这一目标。它们只是 return 作为 TSX 元素的函数的语法糖,因此它们与普通的 Stencil 组件完全不同。主要区别在于它们不编译为 Web 组件,因此只能在 TSX 中工作。但它们也不会产生额外的 DOM 节点,因为它们只是 return 函数 returns.
的模板
让我们举个例子:
@Element() el: HTMLElement;
@Prop() label: string;
render() {
this.el.outerHTML = `<li>${this.label}</li>`;
}
你可以把它写成一个功能组件:
import { FunctionalComponent } from '@stencil/core';
interface ListItemProps {
label: string;
}
export const ListItem: FunctionalComponent<ListItemProps> = ({ label }) => (
<li>{label}</li>
);
然后你就可以像
一样使用它了
import { ListItem } from './ListItem';
@Component({ tag: 'my-comp' })
export class MyComp {
render() {
return (
<ul>
<ListItem label="tab 1" />
<ListItem label="tab 2" />
</ul>
);
}
}
将呈现为
<ul>
<li>tab 1</li>
<li>tab 2</li>
</ul>
除了标签道具,您还可以编写功能组件来接受标签作为子组件:
export const ListItem: FunctionalComponent = (_, children) => (
<li>{children}</li>
);
并像
一样使用它
<ListItem>tab 1</ListItem>
BTW Host
实际上是一个函数组件。要了解有关功能组件(及其限制)的更多信息,请参阅 https://stenciljs.com/docs/functional-components。
虽然我知道这可能是一种糟糕的做法,但我需要构建 StencilJS 组件,以便在 render() 内部,我不想渲染组件标签本身,因为已经存在样式指南并且它期望 DOM 以某种方式构建。这是我要实现的目标 - 组件代码(来自 HTML 或在另一个组件内):
<tab-header-list>
<tab-header label="tab 1"></tab-header>
<tab-header label="tab 2"></tab-header>
</tab-header-list>
渲染时,我希望生成的 DOM 类似于:
<tab-header-list>
<ul>
<li>tab 1</li>
<li>tab 2</li>
</ul>
</tab-header-list>
所以在 tab-header-list render() 函数中,我正在做
return (
<ul>
<slot/>
</ul>
);
我可以在 tab-header render() 函数中执行此操作
@Element() el: HTMLElement;
@Prop() label: string;
render() {
this.el.outerHTML = `<li>${this.label}</li>`;
}
得到我想要的,但我如何使用 TSX 做到这一点? (为简单起见,上面的代码非常简单,但我真正需要构建的是带有事件等的更复杂的 li 标签,所以我想使用 TSX)
试图将 DOM 存储到变量,但我不确定如何将其分配为 this.el(外部 HTML 似乎是我能想到的唯一方法,但我觉得一定有更好的方法)
@Element() el: HTMLElement;
@Prop() label: string;
render() {
var tabheaderDOM = (<li>{this.label}</li>);
// how can I assign above DOM to this.el somehow?
//this.el.outerHTML = ?
}
非常感谢能得到的任何帮助 - 提前感谢您的宝贵时间!
遗憾的是,您不能使用没有标签的自定义元素,但有一个解决方法:
您可以使用 Host
元素作为结果标签的参考。
render () {
return (
<Host>....</Host>
)
}
然后在你的样式表中你可以为它设置 display
属性:
:host {
display: contents;
}
display: contents causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself
注意:它在 IE、opera mini 中不起作用...https://caniuse.com/#feat=css-display-contents
更新:
如果您不使用 shadowDOM
,则需要将 :host
替换为标签名称,例如:
tab-header {
display: contents;
}
功能组件或许可以帮助您实现这一目标。它们只是 return 作为 TSX 元素的函数的语法糖,因此它们与普通的 Stencil 组件完全不同。主要区别在于它们不编译为 Web 组件,因此只能在 TSX 中工作。但它们也不会产生额外的 DOM 节点,因为它们只是 return 函数 returns.
的模板让我们举个例子:
@Element() el: HTMLElement;
@Prop() label: string;
render() {
this.el.outerHTML = `<li>${this.label}</li>`;
}
你可以把它写成一个功能组件:
import { FunctionalComponent } from '@stencil/core';
interface ListItemProps {
label: string;
}
export const ListItem: FunctionalComponent<ListItemProps> = ({ label }) => (
<li>{label}</li>
);
然后你就可以像
一样使用它了import { ListItem } from './ListItem';
@Component({ tag: 'my-comp' })
export class MyComp {
render() {
return (
<ul>
<ListItem label="tab 1" />
<ListItem label="tab 2" />
</ul>
);
}
}
将呈现为
<ul>
<li>tab 1</li>
<li>tab 2</li>
</ul>
除了标签道具,您还可以编写功能组件来接受标签作为子组件:
export const ListItem: FunctionalComponent = (_, children) => (
<li>{children}</li>
);
并像
一样使用它<ListItem>tab 1</ListItem>
BTW Host
实际上是一个函数组件。要了解有关功能组件(及其限制)的更多信息,请参阅 https://stenciljs.com/docs/functional-components。