Skip to content

Commit eaa73bc

Browse files
crisbetommalerba
authored andcommitted
perf(overlay): only compute and emit position changes if there are subscribers (#11431)
When emitting the `ConnectedOverlayPositionChange`, we have to compute whether the overlay is being clipped by the viewport or one of its parent scrollables. These calculations can be expensive, because they need the `ClientRect` of each element, however they won't necessarily be used by the consumer. These changes move things around so we only calculate the scrollable clipping if the consumer has subscribed to the `positionChanges` observable.
1 parent 20562e5 commit eaa73bc

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

src/cdk/overlay/position/flexible-connected-position-strategy.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,19 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
108108
/** Selector to be used when finding the elements on which to set the transform origin. */
109109
private _transformOriginSelector: string;
110110

111+
/** Amount of subscribers to the `positionChanges` stream. */
112+
private _positionChangeSubscriptions = 0;
113+
111114
/** Observable sequence of position changes. */
112-
positionChanges: Observable<ConnectedOverlayPositionChange> =
113-
this._positionChanges.asObservable();
115+
positionChanges: Observable<ConnectedOverlayPositionChange> = Observable.create(observer => {
116+
const subscription = this._positionChanges.subscribe(observer);
117+
this._positionChangeSubscriptions++;
118+
119+
return () => {
120+
subscription.unsubscribe();
121+
this._positionChangeSubscriptions--;
122+
};
123+
});
114124

115125
/** Ordered list of preferred positions, from most to least desirable. */
116126
get positions() {
@@ -581,9 +591,14 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
581591
this._lastPosition = position;
582592

583593
// Notify that the position has been changed along with its change properties.
584-
const scrollableViewProperties = this._getScrollVisibility();
585-
const changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties);
586-
this._positionChanges.next(changeEvent);
594+
// We only emit if we've got any subscriptions, because the scroll visibility
595+
// calculcations can be somewhat expensive.
596+
if (this._positionChangeSubscriptions > 0) {
597+
const scrollableViewProperties = this._getScrollVisibility();
598+
const changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties);
599+
this._positionChanges.next(changeEvent);
600+
}
601+
587602
this._isInitialRender = false;
588603
}
589604

0 commit comments

Comments
 (0)