MutationObserver和IntersectionObserver:揭秘最易被忽视却必不可少的API
2023-09-25 15:34:15
前言
在日常开发中,我们通常会遇到元素的监听需求,不管是元素位置的监听还是元素内容的监听。如果没有原生API的支持,我们通常会想尽一切办法去实现它们,而且各类开源的解决方案也层出不穷。那有没有使用方便、功能强大的API直接支持这些功能呢?答案是肯定的,MutationObserver和IntersectionObserver就是两颗遗珠。这两个API可以轻松实现元素监听的需求,而且用法简单、兼容性良好。本文将详细介绍这两个API的用法和应用场景,帮助开发者们在日常开发中游刃有余。
MutationObserver
MutationObserver是一个可以监听DOM元素变化的API。它可以监听元素的属性变化、子元素的变化以及文本内容的变化。MutationObserver的用法非常简单,首先我们需要创建一个新的MutationObserver对象,然后将要监听的元素和监听的类型传递给这个对象。接下来,我们需要定义一个回调函数,当元素发生变化时,这个回调函数就会被调用。
const observer = new MutationObserver((mutations, observer) => {
for (const mutation of mutations) {
console.log(mutation);
}
});
observer.observe(document.documentElement, {
childList: true,
attributes: true,
characterData: true
});
上面的代码创建一个MutationObserver对象,并监听document.documentElement元素的所有变化。当元素发生变化时,控制台将会输出变化的详细信息。
MutationObserver可以监听的类型有:
childList
:监听元素的子元素的变化。attributes
:监听元素的属性的变化。characterData
:监听元素的文本内容的变化。
MutationObserver是一个非常强大的API,它可以用来创建各种各样的应用程序。例如,我们可以使用MutationObserver来实现表单验证、图像加载和无限滚动。
表单验证
使用MutationObserver可以轻松实现表单验证。我们可以监听表单元素的变化,并在用户提交表单时检查表单是否有效。
const form = document.getElementById('form');
const observer = new MutationObserver((mutations, observer) => {
for (const mutation of mutations) {
if (mutation.target.tagName === 'INPUT') {
validateInput(mutation.target);
}
}
});
observer.observe(form, {
childList: true,
attributes: true,
characterData: true
});
function validateInput(input) {
const value = input.value;
if (value === '') {
input.classList.add('invalid');
} else {
input.classList.remove('invalid');
}
}
上面的代码创建一个MutationObserver对象,并监听表单的所有变化。当表单元素发生变化时,validateInput()函数会被调用,该函数会检查输入元素是否有效。如果输入元素无效,则会添加一个invalid
类到该元素上。
图像加载
MutationObserver可以用来监听图像的加载。我们可以监听图像的src属性的变化,并在图像加载完成后执行某些操作。
const images = document.querySelectorAll('img');
const observer = new MutationObserver((mutations, observer) => {
for (const mutation of mutations) {
if (mutation.target.tagName === 'IMG' && mutation.type === 'attributes') {
if (mutation.attributeName === 'src') {
imageLoaded(mutation.target);
}
}
}
});
observer.observe(document.documentElement, {
childList: true,
attributes: true,
characterData: true,
subtree: true
});
function imageLoaded(image) {
console.log(image.src + ' has been loaded');
}
上面的代码创建一个MutationObserver对象,并监听document.documentElement元素的所有变化。当图像的src属性发生变化时,imageLoaded()函数会被调用,该函数会输出图像的src属性值。
无限滚动
MutationObserver可以用来实现无限滚动。我们可以监听页面底部的元素的变化,并在用户滚动到页面底部时加载更多内容。
const loadMoreButton = document.getElementById('load-more');
const observer = new MutationObserver((mutations, observer) => {
for (const mutation of mutations) {
if (mutation.target === loadMoreButton) {
loadMoreContent();
}
}
});
observer.observe(loadMoreButton, {
attributes: true
});
function loadMoreContent() {
// 加载更多内容
}
上面的代码创建一个MutationObserver对象,并监听loadMoreButton元素的属性变化。当loadMoreButton元素的属性发生变化时,loadMoreContent()函数会被调用,该函数会加载更多内容。
IntersectionObserver
IntersectionObserver是一个可以监听元素位置变化的API。它可以监听元素是否进入或离开视口。IntersectionObserver的用法非常简单,首先我们需要创建一个新的IntersectionObserver对象,然后将要监听的元素和监听的类型传递给这个对象。接下来,我们需要定义一个回调函数,当元素进入或离开视口时,这个回调函数就会被调用。
const observer = new IntersectionObserver((entries, observer) => {
for (const entry of entries) {
console.log(entry);
}
});
observer.observe(document.documentElement);
上面的代码创建一个IntersectionObserver对象,并监听document.documentElement元素的位置变化。当元素进入或离开视口时,控制台将会输出元素的详细信息。
IntersectionObserver可以监听的类型有:
intersectionRatio
:监听元素与视口的相交比例。rootMargin
:监听元素与视口的相交比例的偏移量。threshold
:监听元素与视口的相交比例的阈值。
IntersectionObserver是一个非常强大的API,它可以用来创建各种各样的应用程序。例如,我们可以使用IntersectionObserver来实现懒加载、视差滚动和无限滚动。
懒加载
IntersectionObserver可以用来实现懒加载。我们可以监听图像的进入视口,并在图像进入视口时加载图像。
const images = document.querySelectorAll('img');
const observer = new IntersectionObserver((entries, observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
loadImage(entry.target);
}
}
});
observer.observe(document.documentElement);
function loadImage(image) {
image.src = image.dataset.src;
}
上面的代码创建一个IntersectionObserver对象,并监听document.documentElement元素的所有变化。当图像进入视口时,loadImage()函数会被调用,该函数会加载图像。
视差滚动
IntersectionObserver可以用来实现视差滚动。我们可以监听元素的进入视口,并在元素进入视口时改变元素的样式。
const elements = document.querySelectorAll('.parallax');
const observer = new IntersectionObserver((entries, observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
element.classList.add('parallax-active');
} else {
element.classList.remove('parallax-active');
}
}
});
observer.observe(document.documentElement);
上面的代码创建一个IntersectionObserver对象,并监听document.documentElement元素的所有变化。当元素进入视口时,element.classList.add('parallax-active')会被调用,该函数会为元素添加一个parallax-active
类。当元素离开视口时,element.classList.remove('parallax-active')会被调用,该函数会移除元素的parallax-active
类。
无限滚动
IntersectionObserver可以用来实现无限滚动。我们可以监听页面底部的元素的进入视口,并在用户滚动到页面底部时加载更多内容。
const loadMoreButton = document.getElementById('load-more');
const observer = new IntersectionObserver((entries, observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
loadMoreContent();
}
}
});
observer.observe(loadMoreButton);
function loadMoreContent() {
// 加载更多内容
}
上面的代码创建一个IntersectionObserver对象,并监听loadMoreButton元素的位置变化。当loadMoreButton元素进入视口时,loadMoreContent()函数会被调用,该函数会加载更多内容。
结语
MutationObserver和IntersectionObserver是两个非常强大的API,它们可以用来创建各种各样的应用程序。这些API的使用非常简单,而且兼容性良好。希望本文能够帮助开发者们更好地理解和使用这两个API。