繁体   English   中英

如何使用 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() function 里面,我在做

return (
  <ul>
    <slot/>
  </ul>
);

我可以在 tab-header render() function 中做到这一点

@Element() el: HTMLElement;
@Prop() label: string;

render() {
  this.el.outerHTML = `<li>${this.label}</li>`;
}

得到我想要的,但我怎么能用TSX做到这一点? (为简单起见,上面的代码非常简单,但我真正需要构建的是更复杂的带有事件等的 li 标签,所以我想使用 TSX)

试图将 DOM 存储到变量中,但我不确定如何将其分配为 this.el(outerHTML 似乎是我能想到的唯一方法,但我觉得必须有更好的方法)

@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使元素的子元素看起来好像是元素父元素的直接子元素,忽略元素本身

注意:它在 IE、opera mini 中不起作用... https://caniuse.com/#feat=css-display-contents

升级版:

如果您不使用shadowDOM ,则需要将:host替换为标记名称,例如:

tab-header {
  display: contents;
}

功能组件或许可以帮助您实现这一目标。 它们只是返回 TSX 元素的 function 的语法糖,因此它们与普通 Stencil 组件完全不同。 主要区别在于它们不编译为 web 组件,因此只能在 TSX 中工作。 但它们也不会导致额外的 DOM 节点,因为它们只是返回 function 返回的模板。

让我们举个例子:

@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>

除了 label 道具,您还可以编写功能组件来接受 label 作为孩子:

export const ListItem: FunctionalComponent = (_, children) => (
  <li>{children}</li>
);

并像使用它一样

<ListItem>tab 1</ListItem>

BTW Host实际上是一个功能组件。 要了解有关功能组件的更多信息(以及存在限制),请参阅https://stenciljs.com/docs/functional-components

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM