
前端UI组件【免费下载链接】fastThe adaptive interface system for modern web experiences.项目地址https://gitcode.com/gh_mirrors/fa/fast点击查看免费下载导读PropertyChangeNotifier是microsoft/fast-element响应式系统中按对象属性粒度派发变更通知的Notifier实现也是Observable.getNotifier()为普通对象返回的默认通知器。本文基于 sites/website/src/docs/1.x/api/fast-element.propertychangenotifier.md 的 API 文档结合 notifier.ts 源码与 notifier.pw.spec.ts 测试用例完整讲解其构造函数、source属性、notify/subscribe/unsubscribe三个方法并深入剖析其内部存储与通知路由原理帮助读者掌握在 FAST 应用中直接订阅或驱动对象属性变更的能力。类概览与定位PropertyChangeNotifier实现Notifier接口定义于 notifier.ts其职责是允许订阅者针对对象上的单个属性接收变更通知。API 文档给出的类型签名为export declare class PropertyChangeNotifier implements Notifier与之并列的还有SubscriberSet——一个为少量订阅者场景优化、按主题整体派发通知的Notifier实现。两者的分工在 observable.ts 中体现得很明确Observable.getNotifier()对数组使用数组专用观察器对普通对象则统一创建PropertyChangeNotifier并缓存到WeakMapfunction getNotifierT extends Notifier Notifier(source: any): T { let found source.$fastController ?? notifierLookup.get(source); if (found void 0) { Array.isArray(source) ? (found createArrayObserver(source)) : notifierLookup.set( source, (found new PropertyChangeNotifier(source)), ); } return found; }因此在日常使用 FAST 的observable装饰器或Observable.defineProperty()定义响应式属性时真正承接变更派发工作的正是PropertyChangeNotifier。这也是它成为框架心跳级基础设施的原因。构造函数与 source 属性构造函数(constructor)(source)签名如下constructor(subject: any);PropertyChangeNotifier必须与一个具体的源对象subject绑定。其实现只有两个内部字段notifier.tsexport class PropertyChangeNotifier implements Notifier { private subscribers: Recordstring, SubscriberSet {}; private subjectSubscribers: SubscriberSet | null null; public readonly subject: any; public constructor(subject: any) { this.subject subject; } // ... }subscribers以属性名为键的SubscriberSet字典存放关注某个具体属性的订阅者subjectSubscribers不关心具体属性、订阅对象整体变化的订阅者集合。属性sourceAPI 文档中该属性描述为 The source that property changes are being notified for类型为any即变更通知所对应的源对象。它由构造函数注入并在整个生命周期内只读readonly subjectSubscriberSet在派发通知时会把该 subject 作为handleChange的第一个参数回传给订阅者。方法一subscribe(subscriber, propertyToWatch?)签名subscribe(subscriber: Subscriber, propertyToWatch?: string): void;propertyToWatch是可选参数决定了订阅者被登记的位置notifier.ts传入了属性名订阅者进入subscribers[propertyToWatch]对应的SubscriberSet不存在则惰性创建之后只在该属性变更时收到通知未传属性名订阅者进入subjectSubscribers源对象上任何属性的变更都会通知到它。Subscriber接口notifier.ts要求实现一个方法export interface Subscriber { handleChange(subject: any, args: any): void; }即订阅者只需提供handleChange(subject, args)args在属性级通知中就是发生变更的属性名。方法二notify(propertyName)签名notify(propertyName: string): void;该方法基于指定属性通知所有订阅者。实现只有两行notifier.tspublic notify(propertyName: string): void { this.subscribers[propertyName]?.notify(propertyName); this.subjectSubscribers?.notify(propertyName); }它依次完成两次派发通知订阅了该具体属性的SubscriberSet通知订阅了对象整体变化的subjectSubscribers。在框架内部notify的调用链是属性 setterobservable.ts在值真正改变后执行getNotifier(source).notify(this.name)并在此之前触发可选的xxxChanged(oldValue, newValue)回调。开发者也可以直接调用Observable.notify(source, args)observable.ts手动驱动同一套派发流程。方法三unsubscribe(subscriber, propertyToUnwatch?)签名unsubscribe(subscriber: Subscriber, propertyToUnwatch?: string): void;与subscribe对称传属性名则从subscribers[propertyToUnwatch]中移除不传则从subjectSubscribers中移除notifier.ts。注意实现中使用的是可选链调用若对应集合不存在则静默返回。内部机制基于 SubscriberSet 的性能优化PropertyChangeNotifier本身只做按属性路由真正存储与派发订阅者的是SubscriberSetnotifier.ts。其文档注释明确了设计动机This set is optimized for the most common scenario of 1 or 2 subscribers. With this in mind, it can store a subscriber in an internal field, allowing it to avoid Array#push operations. If the set ever exceeds two subscribers, it upgrades to an array automatically.具体策略是三个内部槽位private sub1: Subscriber | undefined void 0; private sub2: Subscriber | undefined void 0; private spillover: Subscriber[] | undefined void 0;02 个订阅者直接存入sub1/sub2字段订阅时走subscribe的快速分支notifier.ts完全避免Array#push与数组遍历开销第 3 个订阅者加入时一次性升级为数组[sub1, sub2, subscriber]spillover并清空两个字段通知派发notifier.ts未升级时直接调用sub1/sub2的handleChange(subject, args)已升级则遍历spillover数组。去重与移除subscribe会通过has()跳过重复订阅unsubscribe则按索引splice移除。由于 FAST 的模板绑定通常只对单个属性注册 12 个观察者这种设计把最频繁的路径压缩到了字段访问级别是渲染性能的关键保障之一。测试验证按属性粒度的行为契约notifier.pw.spec.ts 对PropertyChangeNotifier做了详尽的参数化测试针对 3 个属性名 × 110 个订阅者的组合逐一验证四类行为仅订阅特定属性subscribe(handler, propertyName)后notify(propertyName)触发、notify(其他属性名)不触发L117-L140同一订阅者订阅多个属性每个属性各建一个SubscriberSet分组各属性能独立收到对应通知未订阅的属性不会被误通知L142-L171按属性取消订阅unsubscribe(subscriber, propertyName)后该属性不再触发而其他仍订阅的属性继续触发L173-L210取消订阅多个属性全部取消后两个属性都不再触发L212-L250。测试中的订阅者统一实现了handleChange(source, propertyName)并把收到的属性名记录到invokedWith数组与Subscriber接口契约完全一致。实际使用场景场景一模板绑定与表达式观察ExpressionNotifierImplementationobservable.ts在watch()中通过getNotifier(propertySource)获取对象的PropertyChangeNotifier并调用notifier.subscribe(this, propertyName)注册按属性订阅在dispose()时调用notifier.unsubscribe(this, current.propertyName)清理。这就是 FAST 模板中:attr、${expr}绑定自动失效并更新的底层路径。场景二元素控制器ElementController会为每个自定义元素创建一个PropertyChangeNotifierelement-controller.tsObservable.getNotifier(element)通过source.$fastController直接命中该实例元素级的属性变化由此驱动视图更新。场景三手动订阅对象属性开发者可直接通过Observable.getNotifier(obj)拿到PropertyChangeNotifier按属性订阅变更import { Observable, type Subscriber } from microsoft/fast-element; const obj { count: 0 }; Observable.defineProperty(obj, count); const subscriber: Subscriber { handleChange(source: any, propertyName: string) { console.log(property ${propertyName} changed on, source); }, }; const notifier Observable.getNotifier(obj); notifier.subscribe(subscriber, count); // 仅关注 count notifier.notify(count); // 手动派发subscriber 被触发 notifier.unsubscribe(subscriber, count);对于不传propertyToWatch的订阅如 watch.ts 和 reactive.pw.spec.ts 中的用法则进入subjectSubscribers任何属性变化都会收到通知。小结PropertyChangeNotifier是 FAST 响应式系统的属性级通知枢纽subscribe/unsubscribe的第二个可选参数实现了按属性定向订阅与对象级全局订阅的二分路由notify(propertyName)一次调用同时驱动两类订阅者底层SubscriberSet的 1/2 槽位 溢出数组策略则保证了最常见场景下的极低开销。理解它的三个方法与内部路由规则即可在自定义元素、状态对象或模板绑定中精确控制变更传播的粒度与时机。进一步阅读可参考接口定义与两个实现observation/notifier.ts默认创建与调用链observation/observable.ts行为契约测试observation/notifier.pw.spec.ts元素控制器中的使用components/element-controller.ts赞分享前端UI组件【免费下载链接】fastThe adaptive interface system for modern web experiences.项目地址https://gitcode.com/gh_mirrors/fa/fast点击查看免费下载相关推荐Soup 项目 README 翻译同步防退化机制解析从 852 漏洞到 870 结构级校验的演进Soup 项目 README 翻译同步防退化机制解析从 852 漏洞到 870 结构级校验的演进 导读 本文以 changelog.d/0.75.0/870.前端UI组件fast-element Controller.onAttributeChangedCallback()深入解析 FASTElement 属性变更回调的底层机制fast element Controller.onAttributeChangedCallback 深入解析 FASTElement 属性变更回调的底层机制前端UI组件FAST microsoft/fast-element Controller.template 属性详解组件模板的读取、设置与渲染时机FAST microsoft/fast element Controller.template 属性详解组件模板的读取、设置与渲染时机 Controller前端UI组件上一篇Element Plus Vue 3 组件库实录83 篇组件文档 虚拟滚动大表格不卡下一篇Readest 设置面板布局陷阱SettingsRow 单行双控件色块 下拉框的正确实现与源码解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考