使用 rxJS 观察 dom 元素的大小调整

gho*_*der 5 javascript resize observable rxjs reactjs

我想div在我的 dom 中的元素中添加一个调整大小的观察者,以便在调整大小时给我一个回调。

我知道它可以使用ResizeObserver完成,但由于所有浏览器都不支持它,我必须为它添加一个polyfill。

我想知道我是否可以使用 rxJS 做同样的事情?只是观察一个 dom 元素并在它调整大小时在回调中做一些事情。

CHA*_*ist 10

我建议直接使用 ResizeObserver API 并使用 Polyfill 来处理,以防浏览器中没有 ResizeObserver [例如 https://www.npmjs.com/package/resize-observer-polyfill]。

我认为可以很容易地使用 ResizeObserver API 创建一个 Resize DOM Observable,如下所示:

function resizeObservable(elem) {
    return new rxjs.Observable(subscriber => {
        var ro = new ResizeObserver(entries => {
            subscriber.next(entries);
        });

        // Observe one or multiple elements
        ro.observe(elem);
        return function unsubscribe() {
            ro.unobserve(elem);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像普通的 RxJS 一样调用它。

resizeObservable(document.querySelector("XXXX"))
    .pipe(
        // ...
    )
    .subscribe(entries => {
        // handle as you like
    });
Run Code Online (Sandbox Code Playgroud)

使用RxJS而不是ResizeObserver直接使用可以有几个优点,尤其是当您要合并 observable 或想要使用运算符时。

例如,当您想创建一个滚动到底部的按钮时,该按钮仅在不在底部时才会出现。然后你可以很容易地做到这一点

const toggleShowBottomBtnObs$ = rxjs.merge(
    rxjs.fromEvent(document.querySelector("XXX", "scroll"),
    resizeObservable(document.querySelector("XXX"))
)
    .pipe(
        rxjs.operators.debounceTime(200),
        rxjs.operators.map(() => isBottom()),
        rxjs.operators.distinctUntilChanged(),
    )
    .subscribe(toggleShowBtn)
Run Code Online (Sandbox Code Playgroud)


Ran*_*urn 4

忽略MutationObserver动画黑客,因为它们不是问题的一部分......

也许在未来。但目前存在这样的限制:

...resize 事件仅在窗口对象 (document.defaultView) 上触发(发送到)。只有在窗口对象上注册的处理程序才会接收事件。

来源: https: //developer.mozilla.org/en-US/docs/Web/Events/resize

否则:

您正在寻找fromEvent()有效 HTMLElement 事件的 rxJS 方法(阅读:不调整大小)。

来自文档: https: //www.learnrxjs.io/operators/creation/fromevent.html

//create observable that emits click events
const source = fromEvent(document.querySelector('#myDiv'), 'click');
const subscribe = source.subscribe(evt => console.log(evt));
Run Code Online (Sandbox Code Playgroud)