使用宿主元素
Stencil 组件在其 render
方法中使用 JSX声明性地渲染它们的子组件。大多数情况下,render()
函数描述了将要被渲染的子元素,但它也可以用于渲染宿主元素本身的属性。
<Host>
Host
函数组件可以在 render 函数的根节点使用,为宿主元素本身设置属性和事件监听器。它的工作原理和其他 JSX 一样:
// Host is imported from '@stencil/core'
import { Component, Host, h } from "@stencil/core";
@Component({ tag: "todo-list" })
export class TodoList {
@Prop() open = false;
render() {
return (
<Host
aria-hidden={this.open ? "false" : "true"}
class={{
"todo-list": true,
"is-open": this.open,
}}
/>
);
}
}
如果 this.open === true
, 将渲染成:
<todo-list class="todo-list is-open" aria-hidden="false"></todo-list>
类似的, 如果 this.open === false
:
<todo-list class="todo-list" aria-hidden="true"></todo-list>
<Host>
是一个虚拟组件,一个由 stencil 公开的虚拟 API,用于声明性地设置宿主元素的属性,它永远不会在 DOM 中呈现,例如,你永远不会在 Chrome 开发者工具中看到 <Host>
。
<Host>
可以作为 <Fragment>
<Host>
也可以用于需要在根级渲染多个组件的情况,例如:
它可以通过render()
方法来实现:
@Component({ tag: "my-cmp" })
export class MyCmp {
render() {
return (
<Host>
<h1>Title</h1>
<p>Message</p>
</Host>
);
}
}
这个 JSX 将渲染以下 HTML:
<my-cmp>
<h1>Title</h1>
<p>Message</p>
</my-cmp>
即使我们不使用 <Host>
来呈现宿主元素中的任何属性,它也是一个有用的 API,可以在根级呈现许多元素。
Element 装饰器
@Element()
装饰器用于访问类实例中的宿主元素。这将返回一个 HTMLElement
的实例,因此可以在这里使用标准的 DOM 方法/事件。
import { Element } from '@stencil/core';
...
export class TodoList {
@Element() el: HTMLElement;
getListHeight(): number {
return this.el.getBoundingClientRect().height;
}
}
为了在初始化类成员时引用宿主元素,你需要使用 TypeScript 的确定赋值断言修饰符来避免类型错误:
import { Element } from '@stencil/core';
...
export class TodoList {
@Element() el!: HTMLElement;
private listHeight = this.el.getBoundingClientRect().height;
}
如果你需要在 prop 或 state 改变时更新宿主元素,你应该在 render()
方法中使用 <Host>
元素执行此操作。
Styling
在 Styling page 你可以看到有关样式设置的完整信息。
通过使用 @Component
装饰器中定义的组件 tag,可以将 CSS 应用到 <Host>
元素上。
@Component({
tag: 'my-cmp',
styleUrl: 'my-cmp.css'
})
...
my-cmp.css:
my-cmp {
width: 100px;
}
Shadow DOM
需要注意的是,当使用 shadow DOM 时,<Host>
元素的样式并不完全相同。你必须使用 :host
而不是 my-cmp
元素选择器。
@Component({
tag: 'my-cmp',
styleUrl: 'my-cmp.css',
shadow: true
})
...
my-cmp.css:
:host {
width: 100px;
}