方案一: 纯css响应式布局
原理: 基于特定元素的宽度 而非视图 进行响应式布局
⚠️ 有兼容性问题
- 观察的元素上
js
container-type :inline-size ;
container-name: drawer-container
- 基于容器宽度的响应式布局定义
js
基于容器宽度(而非视口)的条件样式
@container drawer-container (max-width: 780px) {
.custom-drawer {
position: absolute;
}
}
方案二: css媒体查询的js实现
原理: 通过JS new ResizeObserver监听元素尺寸,动态切换css样式
1.你的场景:
- 用户调整窗口大小 → 触发
ResizeObserver
回调,检测目标元素宽度变化。 - 根据宽度阈值 → 动态修改
data-mode
,切换 CSS 样式。
2. 关键问题分析:
ResizeObserver
本身已经是异步的,浏览器会自动优化,避免强制同步布局(reflow)。requestAnimationFrame
的作用:确保 UI 更新与浏览器渲染帧同步,适合动画或高频视觉更新。throttle
的作用:控制回调执行频率,避免冗余计算。
2.1 需要使用 requestAnimationFrame
?
❌ 通常不需要,因为:
ResizeObserver
回调已经是在布局计算完成后触发,不会导致强制重排。data-mode
的切换是轻量操作(修改 DOM 属性),不涉及复杂渲染或动画。
2.2 是否需要 throttle
?
✅ 推荐使用,但取决于 ResizeObserver
的触发频率:
- 如果用户 快速拖拽窗口边缘 ,
ResizeObserver
可能高频触发(如每秒 100+ 次)。 - 通过
throttle
限制检测频率(如100ms
),可减少不必要的计算。
js
// 纯 throttle,100ms 检测一次(最佳平衡)
const handleResize = throttle((entries) => {
const width = entries[0].contentRect.width;
element.dataset.mode = width >= 768 ? "desktop" : "mobile";
}, 100, { leading: true, trailing: true });
const observer = new ResizeObserver(handleResize);
observer.observe(targetElement);