- 前端
- UI组件
【免费下载链接】fast
The adaptive interface system for modern web experiences.
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两类节点观察指令共享的基接口,包含两个成员:
| 成员 | 类型 | 说明 |
|---|---|---|
property | T | 观察到的节点要赋值到源对象上的属性名 |
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.
相关推荐
Fast-Element children() 指令详解:在 FASTElement 中观察与同步子节点
Fast Element children 指令详解:在 FASTElement 中观察与同步子节点 children 是 @microsoft/fast el
前端UI组件深入解析 fast-element 的 SlottedBehavior.getNodes() 方法与槽节点观察机制
深入解析 fast element 的 SlottedBehavior.getNodes 方法与槽节点观察机制 SlottedBehavior 是 Micros
前端UI组件FAST 子节点观察运行时:@microsoft/fast-element 中 ChildrenBehavior 的完整解析
FAST 子节点观察运行时:@microsoft/fast element 中 ChildrenBehavior 的完整解析 本文基于仓库中 fast elem
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考