新闻详情

新闻详情

首页 / 资讯中心 / 详情

FAST Element 节点观察 API 详解:NodeBehaviorOptions.property 属性在 children 与 slotted 指令中的核心作用

发布时间:2026/9/29 9:01:24来源:尧图网络
FAST Element 节点观察 API 详解:NodeBehaviorOptions.property 属性在 children 与 slotted 指令中的核心作用
前端UI组件【免费下载链接】fastThe adaptive interface system for modern web experiences.项目地址https://gitcode.com/gh_mirrors/fa/fast点击查看免费下载导读NodeBehaviorOptions.property是 microsoft/fast-element 中用于配置节点观察行为Node Observation Behavior的核心选项属性。它的作用简单而关键指定将观察到的节点数组赋值到视图模型source上的哪个属性。理解这个属性是掌握 FAST Element 模板系统中children与slotted两大节点观察指令directive的钥匙——无论是捕获组件的子元素列表还是获取 Shadow DOM 中 slot 的分配节点最终都要通过property选项把结果同步到可观察属性上进而驱动响应式 UI 更新。读完本文你将掌握property的定义、它在节点观察机制中的底层调用路径、与filter/selector的配合方式以及基于仓库源码与官方指南的完整实战写法。一、API 定义一个属性负责观察结果落到哪里该 API 文档页面fast-element.nodebehavioroptions.property.md给出的定义非常精简property: T;文档对其语义的描述只有一句话The property to assign the observed nodes to.观察到的节点将被赋值到的属性。在 NodeBehaviorOptions 这个泛型接口中T是泛型参数通常被实例化为keyof T string即目标视图模型类型上的某个字符串键名。也就是说property的取值通常是视图模型组件类上一个属性的名字字符串比如listItems、slottedNodes。从源码角度验证该接口定义于 packages/fast-element/src/templating/node-observation.tsexport interface NodeBehaviorOptionsT any { /** * The property to assign the observed nodes to. */ property: T; /** * Filters nodes that are synced with the property. * Called one time for each element in the array. * param value - The Node that is being inspected. * param index - The index of the node within the array. * param array - The Node array that is being filtered. */ filter?: ElementsFilter; }可以看到NodeBehaviorOptions只有两个成员必填的property与可选的filter。两者一主一辅property决定写到哪里filter决定写哪些。二、底层机制property 在节点观察指令中的调用路径NodeBehaviorOptions是节点观察体系的配置基座它在源码中有两个继承者ChildListDirectiveOptions用于children指令基于MutationObserver观察子节点SlottedDirectiveOptions用于slotted指令基于 slot 的assignedNodes()与slotchange事件以及它们组合而成的ChildrenDirectiveOptions与SubtreeDirectiveOptions三者共同继承自NodeObservationDirective抽象基类定义于 node-observation.tsproperty属性的实际使用就发生在这个基类的两个关键方法中。1. 绑定阶段bind()首次写入当视图控制器ViewController绑定行为时基类执行bind()bind(controller: ViewController): void { const target controller.targets[this.targetNodeId] as any; target[this._controllerProperty] controller; this.updateTarget(controller.source, this.computeNodes(target)); this.observe(target); controller.onUnbind(this); }这里updateTarget就是真正使用property的地方protected updateTarget(source: any, value: ReadonlyArrayany): void { source[this.options.property] value; }也就是说bind()会将计算出的节点数组以this.options.property为键名直接赋值到视图模型的对应属性上然后才开始启动观察observe。2. 观察阶段节点变化时的增量同步当 DOM 变化时children与slotted各自的观察回调会把新的节点集合重新写回同一个propertychildren指令在MutationObserver的handleEvent中调用this.updateTarget(this.getSource(target), this.computeNodes(target))见 children.tsslotted指令在slotchange事件的handleEvent中执行同样的写入见 slotted.ts。3. 卸载阶段unbind()清空行为解绑时基类会把属性重置为空数组unbind(controller: ViewController): void { const target controller.targets[this.targetNodeId] as any; this.updateTarget(controller.source, emptyArray); this.disconnect(target); target[this._controllerProperty] null; }4.computeNodes()与filter的协作节点在写入property之前会经过computeNodes()的过滤node-observation.tsprotected computeNodes(target: any): Node[] { let nodes this.getNodes(target); if (filter in this.options) { nodes nodes.filter(this.options.filter!); } return nodes; }因此完整的赋值链路为DOM 节点 →getNodes()采集 →computeNodes()过滤 →updateTarget()写入options.property指定的属性。三、与 filter / selector 的配合关系官方 API 文档只描述了property的赋值语义但要在实战中用好它必须理解它与过滤选项的分工。仓库中的 using-directives.md 给出了权威说明选项位置作用是否必填propertyNodeBehaviorOptions指定观察到的节点数组要赋值到的属性名必填filterNodeBehaviorOptions过滤同步到属性的节点回调签名(value: Node, index?: number, array?: Node[]) boolean可选selectorSubtreeDirectiveOptions使用children的subtree选项时必须用 CSS 选择器替代filter指定采集哪些节点使用subtree时必填关键规则使用children的subtree选项时selector是必填的filter让位于selector。这一点在源码 children.ts 中也有印证——getNodes()优先检查selector in this.options命中则用querySelectorAll采集否则退化为childNodesgetNodes(target: Element): Node[] { if (selector in this.options) { return Array.from(target.querySelectorAll(this.options.selector)); } return Array.from(target.childNodes); }官方文档还补充了一条提示using-directives.md把children指令用在template元素即 host 指令模板上可以拿到自定义元素Light DOM 的全部子节点无论它们是否被分配到某个 slot。四、实战一children 指令——捕获子节点并动态同步children(propertyOrOptions)是NodeBehaviorOptions最典型的消费方其官方 API 签名见 fast-element.children.mdexport declare function childrenT any( propertyOrOptions: (keyof T string) | ChildrenBehaviorOptionskeyof T string ): CaptureTypeT;用法 1直接传字符串属性名import { FASTElement, customElement, html, children, repeat, observable } from microsoft/fast-element; const template htmlFriendList ul ${children(listItems)} ${repeat(x x.friends, htmlstring li${x x}/li )} /ul ; customElement({ name: friend-list, template }) export class FriendList extends FASTElement { observable listItems: Node[]; observable friends: string[] []; connectedCallback() { super.connectedCallback(); console.log(this.listItems); } }完整示例见 using-directives.md。要点children(listItems)等价于children({ property: listItems })——源码中children()会对字符串参数做对象归一化children.tsexport function childrenTSource any, TParent any( propertyOrOptions: (keyof TSource string) | ChildrenDirectiveOptionskeyof TSource string, ): CaptureTypeTSource, TParent { if (isString(propertyOrOptions)) { propertyOrOptions { property: propertyOrOptions }; } return new ChildrenDirective(propertyOrOptions); }slotted()也采用了完全相同的归一化逻辑slotted.ts。用法 2传配置对象配合 filter 只保留元素节点import { FASTElement, customElement, html, children, repeat, elements } from microsoft/fast-element; const template htmlFriendList ul ${children({ property: listItems, filter: elements(li) })} ${repeat(x x.friends, htmlstring li${x x}/li )} /ul ;示例见 using-directives.md。这里的elements(li)来自仓库导出的便捷过滤器node-observation.tsexport const elements (selector?: string): ElementsFilter selector ? value value.nodeType 1 (value as HTMLElement).matches(selector) : selectElements;它返回一个只保留元素节点nodeType 1并可选匹配选择器的过滤函数确保listItems只包含li元素而不会混入文本节点。重要时序约束官方文档特别强调与ref指令类似子节点在connectedCallback生命周期事件之前不可用using-directives.md。因此不要在构造函数或connectedCallback之前读取该属性应依赖*Changed回调或connectedCallback之后的时机。五、实战二slotted 指令——捕获 slot 分配节点slotted(propertyOrOptions)观察的是slot的assignedNodes()结果官方 API 定义见 fast-element.slotted.mdexport declare function slottedT any( propertyOrOptions: (keyof T string) | SlottedBehaviorOptionskeyof T string ): CaptureTypeT;典型用法using-directives.mdimport { FASTElement, customElement, html, slotted, observable } from microsoft/fast-element; const template htmlMyElement div slot ${slotted(slottedNodes)}/slot /div ; customElement({ name: my-element, template }) export class MyElement extends FASTElement { observable slottedNodes: Node[]; slottedNodesChanged() { // respond to changes in slotted node } }要点slotted会把分配到该 slot 的节点数组赋值到slottedNodes属性若该属性以observable装饰则在slotchange事件触发后动态更新。与children一样可以传入包含property与filter的配置对象例如slotted({ property: nodes, filter: elements(foo-bar) })过滤逻辑同样由基类computeNodes()统一执行。官方文档还给出了一条实践提示using-directives.md处理 slotted 节点时最好使用 change handler 而非假设节点在connectedCallback中一定存在因为 slot 分配结果可能在该回调之后才确定。六、仓库测试用例property 赋值行为的实证property的赋值语义不仅在源码中清晰可见也被仓库的 Playwright 测试用例直接验证children.pw.spec.ts、slotted.pw.spec.ts。children 测试gathers child nodes测试构造一个含 10 个子节点的div以property: nodes创建ChildrenDirective绑定视图控制器后断言model.nodes与 DOM 子节点逐一同源children.pw.spec.tsconst behavior new ChildrenDirective({ property: nodes, }); behavior.targetNodeId nodeId; const model new Model(); const controller Fake.viewController(targets, behavior); controller.bind(model); const nodesLength model.nodes.length; const childrenLength children.length; const allMatch children.every((c, i) model.nodes[i] c); expect(result.nodesLength).toBe(result.childrenLength); expect(result.allMatch).toBe(true);注意测试中的两个细节其一Model的属性nodes事先通过Observable.defineProperty(Model.prototype, nodes)声明为可观察属性这印证了将观察到的节点赋值给可观察属性是property语义的完整闭环其二property是必填项filter则在带过滤采集测试中追加为filter: elements(foo-bar)children.pw.spec.ts验证了过滤后的数组长度与元素类型。动态更新测试updates child nodes when they change另一个测试验证了property指向的属性会随 DOM 变化而增量更新children.pw.spec.ts先绑定得到 10 个节点的初始结果再向宿主追加 10 个子节点并await Updates.next()断言model.nodes长度同步变为 20 且内容一致。这直接证明了节点变化 → 重新计算 → 写回property指定属性的完整闭环。slotted 测试slotted.pw.spec.ts 中的 gathers nodes from a slot 测试同样以new SlottedDirective({ property: nodes })构造指令并断言模型属性被赋值updates when slotted nodes change with a filter 测试同文件 L249-L318则验证了在slotchange后经elements(foo-bar)过滤的节点集合会重新写回property指定的属性。七、官方备忘速查仓库的 cheat-sheet.md 对两个指令的速查描述如下指令模板写法行为Child Node Captureul ${children(listItems)}/ul观察元素的childNodes变化时同步为数组并赋给元素实例上的listItems属性Slotted Node Captureslot ${slotted(defaultSlotNodes)}/slot观察 slot 的变化将分配节点同步为数组并赋给元素实例上的defaultSlotNodes属性两条速查都明确指向同一语义观察结果最终通过property指定的名字写入组件实例属性。八、小结理解 property 的三个关键点必填且单一职责property是NodeBehaviorOptions中唯一必填的配置项只负责决定观察到的节点数组写入哪个属性其取值通常是组件类上以observable装饰的属性名贯穿绑定、更新、卸载全生命周期无论是childrenMutationObserver 路径还是slottedslotchange 路径最终都由基类 NodeObservationDirective 的updateTarget()统一完成source[this.options.property] value的写入绑定时赋初值、变化时增量同步、解绑时清空与filter/selector分工明确property解决写哪里filter解决写哪些子树观察时则改用必填的selector两者组合即可实现只同步我关心的那部分节点到我的可观察属性这一高频场景。若希望进一步了解相关类型可继续阅读 NodeBehaviorOptions、children()、slotted() 等 API 文档以及 using-directives.md 中的指令专题章节。赞分享前端UI组件【免费下载链接】fastThe adaptive interface system for modern web experiences.项目地址https://gitcode.com/gh_mirrors/fa/fast点击查看免费下载相关推荐Fast-Element children() 指令详解在 FASTElement 中观察与同步子节点Fast Element children 指令详解在 FASTElement 中观察与同步子节点 children 是 microsoft/fast el前端UI组件RIOT OS 中的 Espressif ESP32-Ethernet-Kit V1.1 板级支持以太网、GPIO 与外设配置实战指南RIOT OS 中的 Espressif ESP32 Ethernet Kit V1.1 板级支持以太网、GPIO 与外设配置实战指南 本指南基于 RIOT前端UI组件LeetCode 448 全解找出数组中消失的数字——从哈希集合到原地负标记的四种解法LeetCode 448 全解找出数组中消失的数字——从哈希集合到原地负标记的四种解法 导读 LeetCode 448「Find All Numbers Di前端UI组件上一篇2025重磅升级Intent-Model核心架构解析与实战指南下一篇Pulsar插件开发完全指南从零开始构建你的第一个扩展创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

OpenClaw小龙虾 Windows版部署教程:解压即用,把 settings 改到 TaoToken 2026/9/29 9:54:34

OpenClaw小龙虾 Windows版部署教程:解压即用,把 settings 改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
把上下文讲清楚,Claude Code 才能少走弯路:CLAUDE.md 与 subagent 配置实战 2026/9/29 9:54:34

把上下文讲清楚,Claude Code 才能少走弯路:CLAUDE.md 与 subagent 配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
箱形图:科研数据分布诊断的黄金标准 2026/9/29 9:54:28

箱形图:科研数据分布诊断的黄金标准

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
FPGA verilog can mcp2515 altera xilinx工程代码:把MCP2515控制器IP核移植到TaoToken验证的CAN收发链路 2026/9/29 9:54:28

FPGA verilog can mcp2515 altera xilinx工程代码:把MCP2515控制器IP核移植到TaoToken验证的CAN收发链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
试验机控制器高分辨率模拟前端:从应变电桥到ADC的低噪声设计 2026/9/29 9:54:27

试验机控制器高分辨率模拟前端:从应变电桥到ADC的低噪声设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
STM32底层运行原理与硬件级调试实战 2026/9/29 9:54:20

STM32底层运行原理与硬件级调试实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉