Observer
HTML5 提供了一些 Observer API,用于观察(或监视)特定的 DOM 元素、属性或者文档本身的变化。
MutationObserver
MutationObserver 接口提供了监视对 DOM 树的更改。它可以观察到节点的增加、删除、属性的改变、文本内容的改变等。使用 MutationObserver 可以实现对 DOM 变化的监听。
js
// 选择需要观察变动的节点
const targetNode = document.getElementById('some-id')
// 创建一个观察器实例并传入回调函数,回调将在观察到变动时执行
const observer = new MutationObserver(mutationsList => {
for (const mutation of mutationsList) {
switch (mutation.type) {
case 'childList':
console.log('一个子节点被新增或删除了')
break
case 'attributes':
console.log(`${mutation.attributeName} 属性被修改`)
break
}
}
})
// 以上述配置开始观察目标节点
observer.observe(targetNode, {
attributes: true, // 观察所有监听的节点属性值的变化
childList: true, // 监听 targetNode 的节点新增和删除
subtree: true, // 监听整个子树,包括子树中所有节点的属性
})
// 停止观察
observer.disconnect()IntersectionObserver
IntersectionObserver 接口用于异步监视目标元素与祖先元素或顶级文档视窗(viewport)的交集变化。它可以用于实现懒加载(lazy loading)等功能,以提高性能。
图片懒加载
html
<body>
<!-- default.jpg 为默认显示的图片,data-src 为图片真实路径 -->
<img src="./img/default.jpg" data-src="./img/1.jpg" />
<img src="./img/default.jpg" data-src="./img/2.jpg" />
<img src="./img/default.jpg" data-src="./img/3.jpg" />
<img src="./img/default.jpg" data-src="./img/4.jpg" />
<script>
// 创建观察器
const observer = new IntersectionObserver(entries => {
entries.forEach(e => {
// 元素进入视口
if (e.isIntersecting) {
// 将 img 的 src 替换为真实的路径
e.target.src = e.target.dataset.src
}
})
})
// 监听所有图片
document.querySelectorAll('img').forEach(el => {
observer.observe(el)
})
</script>
</body>触底加载更多
html
<ul>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
</ul>
<footer>底部</footer>js
// 列表数据
const list = document.querySelector('ul')
// 底部元素,滚动到这里时加载更多
const footer = document.querySelector('footer')
// 创建观察器
const observer = new IntersectionObserver(entries => {
entries.forEach(el => {
// 元素进入视口
if (el.isIntersecting) {
// 加载更多数据
loadMore()
}
})
})
// 监听元素
observer.observe(footer)
async function loadMore() {
const data = await fetch('/api/list').then(res => res.json())
for (const item of data) {
list.innerHTML += `<li>${item}</li>`
}
}ResizeObserver
ResizeObserver 接口用于监视元素的大小变化。当元素的大小发生变化时,会触发回调函数。
html
<body>
<div style="width: 100%; height: 200px; background: #ccc"></div>
<script>
// 创建观察器
const observer = new ResizeObserver(() => {
// 尺寸变化后做的事
console.log(div.clientWidth)
})
// 监听元素
const div = document.querySelector('div')
observer.observe(div)
// 移除监听器
window.addEventListener('unload', () => {
observer.unobserve(div)
})
</script>
</body>