Match-id-165f210a5dda1d08fe348888121abc112590ceac

This commit is contained in:
* 2022-04-07 11:50:51 +08:00 committed by *
parent e851c5a37e
commit f5600dd58c
2 changed files with 111 additions and 0 deletions

View File

@ -0,0 +1,78 @@
/**
*
* ResizeObserver IE
* dom
* window resize object
* window object dom dom dom
* dom window window
* dom
*
* <div id='test'>
* <object> --> div
* <html></html> --> resize
* </object>
* </div>
*
*/
function timeout(fn) {
return setTimeout(fn, 20);
}
function requestFrame(fn) {
const raf = requestAnimationFrame || timeout;
return raf(fn);
}
function cancelFrame(id) {
const cancel = cancelAnimationFrame || clearTimeout;
cancel(id);
}
// 在闲置帧触发回调事件,如果在本次触发前存在未处理回调事件,
// 需要取消未处理的回调事件
function resizeListener(event) {
const win = event.target;
if (win.__resizeRAF__) {
cancelFrame(win.__resizeRAF__);
}
win.__resizeRAF__ = requestFrame(function () {
const observeElement = win.__observeElement__;
observeElement.__resizeCallbacks__.forEach(function (fn) {
fn.call(observeElement, observeElement, event);
});
});
}
function loadObserver() {
// 将待观测元素传递给 object 标签的 window 对象,这样在触发 resize 事件时可以拿到待观测元素
this.contentDocument.defaultView.__observeElement__ = this.__observeElement__;
// 给 html 的 window 对象添加 resize 事件
this.contentDocument.defaultView.addEventListener('resize', resizeListener);
}
export function addResizeListener(element: any, fn: any) {
if (!element.__resizeCallbacks__) {
element.__resizeCallbacks__ = [fn];
element.style.position = 'relative';
const observer = document.createElement('object');
observer.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
observer.data = 'about:blank';
observer.onload = loadObserver;
observer.type = 'text/html';
observer.__observeElement__ = element;
element.__observer__ = observer;
element.appendChild(observer);
} else {
element.__resizeCallbacks__.push(fn);
}
}
export function removeResizeListener(element, fn) {
element.__resizeCallbacks__.splice(element.__resizeCallbacks__.indexOf(fn), 1);
if (!element.__resizeCallbacks__.length) {
element.__observer__.contentDocument.defaultView.removeEventListener('resize', resizeListener);
element.removeChild(element.__observer__);
element.__observer__ = null;
}
}

View File

@ -0,0 +1,33 @@
import { useEffect, useState, useRef } from 'horizon';
import { addResizeListener, removeResizeListener } from './ResizeEvent';
export function SizeObserver(props) {
const { children, ...rest } = props;
const containerRef = useRef();
const [size, setSize] = useState();
const notifyChild = (element) => {
setSize({
width: element.offsetWidth,
height: element.offsetHeight,
});
};
useEffect(() => {
const element = containerRef.current;
setSize({
width: element.offsetWidth,
height: element.offsetHeight,
});
addResizeListener(element, notifyChild);
return () => {
removeResizeListener(element, notifyChild);
};
}, []);
const myChild = size ? children(size.width, size.height) : null;
return (
<div ref={containerRef} {...rest}>
{myChild}
</div>
);
}