mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Refactored element observables, removed memleaks
This commit is contained in:
parent
989b8597c5
commit
8a6b89ffe1
@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Observable, fromEvent, merge } from "rxjs"
|
import { Observable, fromEvent, merge } from "rxjs"
|
||||||
import { map, shareReplay, startWith } from "rxjs/operators"
|
import { map, startWith } from "rxjs/operators"
|
||||||
|
|
||||||
import { getActiveElement } from "../_"
|
import { getActiveElement } from "../_"
|
||||||
|
|
||||||
@ -62,7 +62,6 @@ export function watchElementFocus(
|
|||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
map(({ type }) => type === "focus"),
|
map(({ type }) => type === "focus"),
|
||||||
startWith(el === getActiveElement()),
|
startWith(el === getActiveElement())
|
||||||
shareReplay(1)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Observable, fromEvent, merge } from "rxjs"
|
import { Observable, fromEvent, merge } from "rxjs"
|
||||||
import { map, shareReplay, startWith } from "rxjs/operators"
|
import { map, startWith } from "rxjs/operators"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
@ -71,7 +71,6 @@ export function watchElementOffset(
|
|||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
map(() => getElementOffset(el)),
|
map(() => getElementOffset(el)),
|
||||||
startWith(getElementOffset(el)),
|
startWith(getElementOffset(el))
|
||||||
shareReplay(1)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,23 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import ResizeObserver from "resize-observer-polyfill"
|
import ResizeObserver from "resize-observer-polyfill"
|
||||||
import { Observable, fromEventPattern } from "rxjs"
|
import {
|
||||||
import { shareReplay, startWith } from "rxjs/operators"
|
NEVER,
|
||||||
|
Observable,
|
||||||
|
Subject,
|
||||||
|
defer,
|
||||||
|
merge,
|
||||||
|
of
|
||||||
|
} from "rxjs"
|
||||||
|
import {
|
||||||
|
filter,
|
||||||
|
finalize,
|
||||||
|
map,
|
||||||
|
shareReplay,
|
||||||
|
startWith,
|
||||||
|
switchMap,
|
||||||
|
tap
|
||||||
|
} from "rxjs/operators"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
@ -36,6 +51,40 @@ export interface ElementSize {
|
|||||||
height: number /* Element height */
|
height: number /* Element height */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Data
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize observer entry subject
|
||||||
|
*/
|
||||||
|
const entry$ = new Subject<ResizeObserverEntry>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize observer observable
|
||||||
|
*
|
||||||
|
* This observable will create a `ResizeObserver` on the first subscription
|
||||||
|
* and will automatically terminate it when there are no more subscribers.
|
||||||
|
* It's quite important to centralize observation in a single `ResizeObserver`,
|
||||||
|
* as the performance difference can be quite dramatic, as the link shows.
|
||||||
|
*
|
||||||
|
* @see https://bit.ly/3iIYfEm - Google Groups on performance
|
||||||
|
*/
|
||||||
|
const observer$ = defer(() => of(
|
||||||
|
new ResizeObserver(entries => {
|
||||||
|
for (const entry of entries)
|
||||||
|
entry$.next(entry)
|
||||||
|
})
|
||||||
|
))
|
||||||
|
.pipe(
|
||||||
|
switchMap(resize => merge(of(resize), NEVER)
|
||||||
|
.pipe(
|
||||||
|
finalize(() => resize.disconnect())
|
||||||
|
)
|
||||||
|
),
|
||||||
|
shareReplay({ bufferSize: 1, refCount: true })
|
||||||
|
)
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Functions
|
* Functions
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
@ -59,6 +108,11 @@ export function getElementSize(el: HTMLElement): ElementSize {
|
|||||||
/**
|
/**
|
||||||
* Watch element size
|
* Watch element size
|
||||||
*
|
*
|
||||||
|
* This function returns an observable that will subscribe to a single internal
|
||||||
|
* instance of `ResizeObserver` upon subscription, and emit resize events until
|
||||||
|
* termination. Note that this function should not be called with the same
|
||||||
|
* element twice, as the first unsubscription will terminate observation.
|
||||||
|
*
|
||||||
* @param el - Element
|
* @param el - Element
|
||||||
*
|
*
|
||||||
* @return Element size observable
|
* @return Element size observable
|
||||||
@ -66,15 +120,19 @@ export function getElementSize(el: HTMLElement): ElementSize {
|
|||||||
export function watchElementSize(
|
export function watchElementSize(
|
||||||
el: HTMLElement
|
el: HTMLElement
|
||||||
): Observable<ElementSize> {
|
): Observable<ElementSize> {
|
||||||
return fromEventPattern<ElementSize>(next => {
|
return observer$
|
||||||
new ResizeObserver(([{ contentRect }]) => next({
|
|
||||||
width: Math.round(contentRect.width),
|
|
||||||
height: Math.round(contentRect.height)
|
|
||||||
}))
|
|
||||||
.observe(el)
|
|
||||||
})
|
|
||||||
.pipe(
|
.pipe(
|
||||||
startWith(getElementSize(el)),
|
tap(observer => observer.observe(el)),
|
||||||
shareReplay(1)
|
switchMap(observer => entry$
|
||||||
|
.pipe(
|
||||||
|
filter(({ target }) => target === el),
|
||||||
|
finalize(() => observer.unobserve(el)),
|
||||||
|
map(({ contentRect }) => ({
|
||||||
|
width: contentRect.width,
|
||||||
|
height: contentRect.height
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
startWith(getElementSize(el))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user