perf: improve attribute selectors by adding single listeners (#10384)

This commit is contained in:
Eduardo Speroni
2024-06-28 18:55:12 -03:00
committed by GitHub
parent b8fff3833e
commit bb83addb5c
3 changed files with 19 additions and 7 deletions

View File

@@ -6,6 +6,7 @@ export namespace CSSUtils {
export const CLASS_PREFIX = 'ns-';
export const MODAL_ROOT_VIEW_CSS_CLASS = `${CLASS_PREFIX}${MODAL}`;
export const ROOT_VIEW_CSS_CLASS = `${CLASS_PREFIX}${ROOT}`;
export const IgnoredCssDynamicAttributeTracking = new Set<string>();
export function getSystemCssClasses(): string[] {
return cssClasses;

View File

@@ -5,6 +5,7 @@ import { Trace } from '../../trace';
import { isNullOrUndefined } from '../../utils/types';
import * as ReworkCSS from '../../css';
import { CSSUtils } from '../../css/system-classes';
/**
* An interface describing the shape of a type on which the selectors may apply.
@@ -1014,6 +1015,9 @@ export class SelectorsMatch<T extends Node> implements ChangeAccumulator {
public selectors: SelectorCore[];
public addAttribute(node: T, attribute: string): void {
if (CSSUtils.IgnoredCssDynamicAttributeTracking.has(attribute)) {
return;
}
const deps: Changes = this.properties(node);
if (!deps.attributes) {
deps.attributes = new Set();

View File

@@ -22,6 +22,7 @@ import * as capm from './css-animation-parser';
import { sanitizeModuleName } from '../../utils/common';
import { resolveModuleName } from '../../module-name-resolver';
import { cleanupImportantFlags } from './css-utils';
import { Observable, PropertyChangeData } from '../../data/observable';
let cssAnimationParserModule: typeof capm;
function ensureCssAnimationParserModule() {
@@ -418,6 +419,8 @@ export class CssState {
_matchInvalid: boolean;
_playsKeyframeAnimations: boolean;
private _dynamicUpdateListenerMap: Map<ViewBase, (t: any) => void> = new Map();
constructor(private viewRef: WeakRef<ViewBase>) {
this._onDynamicStateChangeHandler = () => this.updateDynamicState();
}
@@ -650,9 +653,14 @@ export class CssState {
const changeMap = this._match.changeMap;
changeMap.forEach((changes, view) => {
if (changes.attributes) {
changes.attributes.forEach((attribute) => {
view.addEventListener(attribute + 'Change', this._onDynamicStateChangeHandler);
});
const attributes = changes.attributes;
const listener = (args: PropertyChangeData) => {
if (attributes.has(args.propertyName)) {
this._onDynamicStateChangeHandler();
}
};
this._dynamicUpdateListenerMap.set(view, listener);
view.addEventListener(Observable.propertyChangeEvent, listener);
}
if (changes.pseudoClasses) {
changes.pseudoClasses.forEach((pseudoClass) => {
@@ -669,10 +677,8 @@ export class CssState {
private unsubscribeFromDynamicUpdates(): void {
this._appliedChangeMap.forEach((changes, view) => {
if (changes.attributes) {
changes.attributes.forEach((attribute) => {
view.removeEventListener(attribute + 'Change', this._onDynamicStateChangeHandler);
});
if (this._dynamicUpdateListenerMap.has(view)) {
view.removeEventListener(Observable.propertyChangeEvent, this._dynamicUpdateListenerMap.get(view));
}
if (changes.pseudoClasses) {
changes.pseudoClasses.forEach((pseudoClass) => {
@@ -684,6 +690,7 @@ export class CssState {
});
}
});
this._dynamicUpdateListenerMap.clear();
this._appliedChangeMap = CssState.emptyChangeMap;
}