☰
FAST Element SlottedBehaviorOptions 接口详解:用 `slotted` 指令配置插槽节点观察
2026/9/29 3:13:03 网站建设 项目流程
  • 前端
  • UI组件

【免费下载链接】fast

The adaptive interface system for modern web experiences.

项目地址:https://gitcode.com/gh_mirrors/fa/fast
点击查看免费下载

SlottedBehaviorOptions是 Microsoft FAST Element 中用于配置slotted 节点观察(即监听<slot>元素assignedNodes()变化)的核心选项接口。本文围绕该接口的完整签名、继承来源、源码实现与实战用法展开,帮助你在自定义元素模板中精准收集和响应插槽分配节点,并能读懂仓库中与之对应的slotted()指令与SlottedBehavior运行机制。

接口概览:一次接口,三个来源

在 1.x 版本 API 文档中,该接口的定义如下(见 fast-element.slottedbehavioroptions.md):

export interface SlottedBehaviorOptions<T = any> extends NodeBehaviorOptions<T>, AssignedNodesOptions

接口描述为"The options used to configure slotted node observation"——即配置 slotted 节点观察所用的选项集合。它不定义任何自有成员,而是通过多重继承组合了两个来源的配置能力:

  • NodeBehaviorOptions<T>:fast-element 自身的节点观察通用选项,提供目标属性名与过滤函数;
  • AssignedNodesOptions:来自 TypeScript DOM 标准库(lib.dom.d.ts)的类型,对应浏览器原生HTMLSlotElement.assignedNodes()的调用参数(即{ flatten?: boolean })。

需要留意的是:在 当前仓库 的源码中,该接口已演进命名为SlottedDirectiveOptions<T> extends NodeBehaviorOptions<T>, AssignedNodesOptions(见 api-report.api.md 第 991 行),语义与 1.x 文档中的SlottedBehaviorOptions完全一致。这份文档页面本身由 API Documenter 自动生成,属于 API 参考页,因此结合源码阅读最能还原其真实行为。

继承之一:NodeBehaviorOptions —— 目标属性与过滤

NodeBehaviorOptions<T>定义于 node-observation.ts,是children与slotted两类节点观察指令共享的基接口,包含两个成员:

成员类型说明
propertyT观察到的节点要赋值到源对象上的属性名
filter?ElementsFilter节点过滤函数,对数组中的每个元素各调用一次,仅通过过滤的节点会同步到属性

其中ElementsFilter的类型签名是:

export type ElementsFilter = (value: Node, index?: number, array?: Node[]) => boolean;

fast-element 还内置了一个elements(selector?)工厂函数(node-observation.ts),用于生成"只保留元素节点"的过滤器:不传参数时仅检查nodeType === 1(即 ELEMENT_NODE);传入 CSS 选择器时还会额外调用element.matches(selector)做精配过滤。

继承之二:AssignedNodesOptions —— flatten 透传

AssignedNodesOptions并非 fast-element 自定义类型,而是 TypeScript DOM 库为原生HTMLSlotElement.assignedNodes(options?)定义的标准参数类型,其唯一可选成员是flatten?: boolean:

  • flatten: false(默认):仅返回直接分配给该插槽的节点;
  • flatten: true:返回该插槽在影子树中"展开"后的完整分配节点集(包括嵌套插槽分配过来的节点)。

从 slotted.ts 的实现可以看到,该选项会被原样透传给浏览器原生 API:

getNodes(target: HTMLSlotElement): Node[] { return target.assignedNodes(this.options); }

也就是说,你在SlottedBehaviorOptions中配置的flatten值会直接作用于assignedNodes()的调用,最终返回结果再经过filter处理后才写入目标属性。

源码实现:从 option 到行为的完整链路

理解了接口成员后,再看它如何被消费。1.x 文档中的SlottedBehavior类(见 fast-element.slottedbehavior.md)签名如下:

export declare class SlottedBehavior extends NodeObservationBehavior<SlottedBehaviorOptions>

其构造函数接收(target: HTMLSlotElement, options: SlottedBehaviorOptions),并实现了三个方法:observe()、disconnect()、getNodes()。在当前源码中对应SlottedDirective(slotted.ts),关键行为包括:

  • 监听slotchange事件:observe(target)通过target.addEventListener("slotchange", this)开始观察,disconnect(target)移除监听(对应文档页中的 observe/disconnect 方法)。每当插槽分配节点变化时触发回调;
  • 更新目标属性:handleEvent中调用updateTarget(this.getSource(target), this.computeNodes(target)),把最新节点写入源对象的property属性;
  • 应用 filter:computeNodes在基类 node-observation.ts 中实现——先取原生assignedNodes()结果,若 options 中存在filter则执行nodes.filter(this.options.filter),过滤发生在节点赋值之前;
  • 解绑清理:unbind时先将空数组写入属性,再移除事件监听,避免内存泄漏。

实战用法一:字符串简写与 options 对象

slotted()指令是使用该选项接口的入口。其 1.x 签名(fast-element.slotted.md)为:

export declare function slotted<T = any>(propertyOrOptions: (keyof T & string) | SlottedBehaviorOptions<keyof T & string>): CaptureType<T>;

即参数既可以是一个属性名字符串,也可以是完整的SlottedBehaviorOptions对象。当传入字符串时,源码 slotted.ts 会将其转换为{ property: propertyOrOptions }简写形式。

最简单的用法——直接传入属性名(示例取自 using-directives.md):

import { FASTElement, customElement, html, slotted } from '@microsoft/fast-element'; const template = html<MyElement>` <div> <slot ${slotted('slottedNodes')}></slot> </div> `; @customElement({ name: 'my-element', template }) export class MyElement extends FASTElement { @observable slottedNodes: Node[]; slottedNodesChanged() { // 响应插槽节点变化 } }

要点说明:

  • slottedNodes会被填充为该插槽分配的所有节点;若用@observable修饰,则节点变化时会动态更新;
  • 可以同时实现*Changed变更回调(如slottedNodesChanged)以响应节点变化;
  • 官方指南明确建议:优先依赖变更处理器来读取插槽节点,而不是假定节点在connectedCallback中已存在(详见 using-directives.md)。

实战用法二:完整配置 —— filter 与 flatten 的组合

当需要自定义行为时,改为传入完整的 options 对象,把NodeBehaviorOptions与AssignedNodesOptions的能力组合起来。例如只想收集被分配的foo-bar元素节点:

import { html, slotted, elements } from '@microsoft/fast-element'; const template = html<MyElement>` <div> <slot ${slotted({ property: 'slottedNodes', filter: elements('foo-bar'), flatten: false })}></slot> </div> `;

配置含义拆解:

  • property:必需项,指定写入节点数组的属性名;
  • filter: elements('foo-bar'):只保留匹配foo-bar的元素节点,其余文本节点、注释节点与不匹配元素被剔除;
  • flatten: false:仅取直接分配给该 slot 的节点,不展开嵌套插槽。

更细粒度地,filter也可以是任意自定义的ElementsFilter函数,例如只保留偶数下标元素:filter: (node, index) => index % 2 === 0。该函数会对每个节点各执行一次,接收value、index、array三个参数。

测试验证:仓库中的行为证据

接口的每一个行为都能在 Playwright 测试 slotted.pw.spec.ts 中找到对应验证:

  • 节点收集(第 41-103 行):在宿主上追加 10 个子节点后,构造new SlottedDirective({ property: "nodes" })并bind,断言model.nodes与子节点数组逐项相等;
  • filter 过滤(第 105-173 行):以{ property: "nodes", filter: elements("foo-bar") }配置后,断言仅收集到匹配foo-bar的子集,与children.filter(elements("foo-bar"))结果一致;
  • 动态更新(第 175-240 行):bind 之后向宿主追加新的子节点,等待Updates.next()(fast-element 的批量更新队列),断言model.nodes同步增长到最新数量。

这些用例印证了该选项接口"收集 → 过滤 → 动态同步"的完整语义:property决定写往哪里,filter决定写入什么,flatten决定原生层取到哪些节点,而slotchange事件驱动了持续更新。

与 children 指令的对照小结

SlottedBehaviorOptions与children指令共享NodeBehaviorOptions基类,两者的核心差异在于观察对象与原生调用:

  • slotted:观察<slot>元素的分配节点,底层调用HTMLSlotElement.assignedNodes(options),因此支持flatten透传;
  • children:观察元素子节点(light DOM / shadow DOM 内的直接子节点),使用MutationObserver一类机制,不支持flatten。

选择哪个取决于你的组件需要跟踪"插槽分配"还是"直接子节点"。官方文档还指出:若在children中使用subtree选项,则必须用selector形式的 filter(参见 using-directives.md),而slotted始终可以自由组合filter与flatten。

相关参考

  • 接口参考页:fast-element.slottedbehavioroptions.md、fast-element.nodebehavioroptions.md
  • 行为类与指令:fast-element.slottedbehavior.md、fast-element.slotted.md
  • 源码实现:slotted.ts、node-observation.ts
  • 使用指南:using-directives.md(含slotted指令完整示例与最佳实践)
  • 测试用例:slotted.pw.spec.ts
  • 前端
  • UI组件

【免费下载链接】fast

The adaptive interface system for modern web experiences.

项目地址:https://gitcode.com/gh_mirrors/fa/fast
点击查看免费下载
上一篇:3分钟学会无损视频剪辑:告别重新编码的漫长等待
下一篇:怎样3步解锁VMware对macOS的支持:完整安装指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询