ResizeObserver
是一个用于监听元素尺寸变化的 JavaScript API。它可以在不依赖轮询或事件冒泡的情况下,高效地检测元素尺寸的变化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ResizeObserver Example</title>
<style>
#observedElement {
background-color: #f0f0f0;
padding: 10px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="observedElement">This is an observed element.</div>
<div class="info"></div>
<script>
const observedElement = document.getElementById('observedElement');
const info = document.querySelector('.info');
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
console.log(`Element's new size: ${entry.contentRect.width} x ${entry.contentRect.height}`, entry.target.textContent);
info.textContent = `Element's new size: ${entry.contentRect.width} x ${entry.contentRect.height}`;
}
});
resizeObserver.observe(observedElement);
</script>
</body>
</html>
上述示例中:
ResizeObserver
实例,并传入一个回调函数。当观察的元素尺寸发生变化时,回调函数会被触发,并且会接收到一个包含观察元素信息的entries
数组。entries
数组,通过entry.contentRect
可以获取到元素的新尺寸信息。observe
方法开始观察指定的元素。ResizeObserver
在响应式布局、动态调整元素大小等场景中非常有用,可以避免频繁的轮询操作,提高性能。
一、响应式图片布局
当窗口大小变化时,根据容器的尺寸动态调整图片的大小,以确保图片在不同屏幕尺寸下都能良好显示。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Image with ResizeObserver</title>
<style>
.image-container {
width: 50%;
border: 1px solid #ccc;
}
img {
width: 100%;
height: auto;
}
</style>
</head>
<body>
<div class="image-container">
<img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/48950506dec046379133b3e851f4eb87~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5LiA6LW36YeN5a2m5YmN56uv:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMTQwMzg1MTA2NzkxOTExIn0%3D&rk3s=f64ab15b&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1726885385&x-orig-sign=n8KsLmSdp6fAD%2FQDT9hwzQ1oYf4%3D" alt="Image">
</div>
<div class="imageText"></div>
<script>
const imageContainer = document.querySelector('.image-container');
const img = document.querySelector('img');
const imageText = document.querySelector('.imageText');
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
const newWidth = entry.contentRect.width;
img.style.width = newWidth + 'px';
imageText.textContent = `Image width: ${newWidth}px`;
}
});
resizeObserver.observe(imageContainer);
</script>
</body>
</html>
二、自适应导航栏
根据窗口宽度调整导航栏的样式,例如在小屏幕下转换为移动端菜单样式。
大屏
小屏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Adaptive Navbar with ResizeObserver</title>
<style>
nav {
display: flex;
justify-content: space-between;
padding: 10px;
}
@media (max-width: 768px) {
nav {
flex-direction: column;
}
}
</style>
</head>
<body>
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>
<script>
const nav = document.querySelector('nav');
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
if (entry.contentRect.width <= 768) {
nav.classList.add('mobile-nav');
} else {
nav.classList.remove('mobile-nav');
}
}
});
resizeObserver.observe(nav);
</script>
</body>
</html>
三、动态布局调整
在复杂的页面布局中,根据某个关键元素的尺寸变化,动态调整其他元素的位置和大小。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic Layout with ResizeObserver</title>
<style>
.main-content {
display: flex;
background-color: #ccc;
padding: 20px;
}
.sidebar {
width: 200px;
background-color: #f0f0f0;
padding: 10px;
}
.content {
flex: 1;
background-color: #999;
}
</style>
</head>
<body>
<div class="main-content">
<div class="sidebar"></div>
<div class="content"></div>
</div>
<script>
const mainContent = document.querySelector('.main-content');
const sidebar = document.querySelector('.sidebar');
const content = document.querySelector('.content');
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
const newWidth = entry.contentRect.width;
sidebar.style.width = newWidth > 800? 200 : 100 + 'px';
content.style.width = newWidth - sidebar.offsetWidth + 'px';
}
});
resizeObserver.observe(mainContent);
</script>
</body>
</html>
ResizeObserver
虽然很有用,但也存在一些局限性:
一、浏览器兼容性
并非所有浏览器都完全支持ResizeObserver
。一些较旧的浏览器可能不支持这个 API,这就需要使用垫片(polyfill)或者考虑其他替代方案来确保在不同浏览器环境下的功能一致性。例如,在一些旧版本的 Internet Explorer 中无法使用。
通过以下几种方式解决ResizeObserver
的浏览器兼容性问题:
可以使用ResizeObserver
的 polyfill 库,例如resize-observer-polyfill
。
npm install resize-observer-polyfill
import ResizeObserver from 'resize-observer-polyfill';
const observer = new ResizeObserver(entries => {
// 处理尺寸变化
});
observer.observe(document.getElementById('myElement'));
1.进行特征检测:
const isResizeObserverSupported = typeof ResizeObserver!== 'undefined';
2.如果不支持ResizeObserver
,可以使用其他方式来模拟尺寸变化的监测,比如使用定时器进行轮询检测元素尺寸变化,但这种方式性能相对较差。
let elementWidth;
let elementHeight;
const checkSize = () => {
const element = document.getElementById('myElement');
const newWidth = element.offsetWidth;
const newHeight = element.offsetHeight;
if (newWidth!== elementWidth || newHeight!== elementHeight) {
elementWidth = newWidth;
elementHeight = newHeight;
// 处理尺寸变化
}
};
setInterval(checkSize, 100);
二、性能考虑
虽然ResizeObserver
相比传统的轮询或事件监听方式在性能上有很大提升,但如果同时观察大量元素,或者在复杂的布局场景下频繁触发尺寸变化,仍然可能会对性能产生一定影响。特别是在一些资源受限的设备上,可能会出现卡顿现象。
三、观察对象限制
只能观察 DOM 元素的尺寸变化,对于其他类型的对象(如 SVG 元素、Canvas 元素等非传统 DOM 元素)的尺寸变化无法直接观察,可能需要通过间接的方式或者其他特定的技术来实现对这些对象尺寸变化的监测。
四、复杂布局场景下的不确定性
在非常复杂的布局场景中,尤其是涉及到多个嵌套的、具有复杂 CSS 属性和定位的元素时,ResizeObserver
可能无法准确地反映出元素的实际可视尺寸变化。例如,当元素的尺寸受到父元素的transform
、filter
等属性影响时,ResizeObserver
可能无法准确捕捉到这些变化对元素最终尺寸的影响。
MutationObserver
和ResizeObserver
的区别一、监测目标
二、触发条件
MutationObserver
会通知开发者。三、使用场景
MutationObserver:
MutationObserver
。ResizeObserver:
四、性能影响
两者在使用不当的情况下都可能对性能产生一定影响,但影响方式略有不同:
MutationObserver
更加高效,因为它不会对其他无关的 DOM 变化做出响应。腾讯技术创作特训营s9
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。