diff --git a/libs/extension/src/components/ResizeEvent.ts b/libs/extension/src/components/ResizeEvent.ts
new file mode 100644
index 00000000..0150d0ad
--- /dev/null
+++ b/libs/extension/src/components/ResizeEvent.ts
@@ -0,0 +1,78 @@
+/**
+ *
+ * 由于 ResizeObserver 对 IE 和低版本主流浏览器不兼容,需要我们自己解决这个问题。
+ * 这是一个不依赖任何框架的监听 dom 元素尺寸变化的解决方案。
+ * 浏览器出于性能的考虑,只有 window 的 resize 事件会触发。我们通过 object 标签可以得到
+ * 一个 window 对象,让 object dom 元素成为待观测 dom 的子元素,并且和待观测 dom 大小一致。
+ * 这样一旦待观测 dom 的大小发生变化, window 的大小也会发生变化,我们就可以通过监听 window
+ * 大小变化的方式监听待观测 dom 的大小变化。
+ *
+ *
+ *
+ *
+ *
+ */
+
+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;
+ }
+}
diff --git a/libs/extension/src/components/SizeObserver.tsx b/libs/extension/src/components/SizeObserver.tsx
new file mode 100644
index 00000000..3d430093
--- /dev/null
+++ b/libs/extension/src/components/SizeObserver.tsx
@@ -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 (
+
+ {myChild}
+
+ );
+}
\ No newline at end of file