比如 元素从不可见到可见
、元素大小的改变
、元素的属性和子节点的修改
等等,这类事件的监听,浏览器提供了 5 种 Observer
来监听这些变动:MutationObserver
、IntersectionObserver
、PerformanceObserver
、ResizeObserver
、ReportingObserver
IntersectionObserver
它可以监听一个元素和可视区域相交部分的比例,然后在可视比例达到某个阈值的时候触发回调。
用法
new IntersectionObserver(callback, options)
const options = {
root: null,
rootMargin: 0,
thresholds: 1,
}
const io = new IntersectionObserver((entries) => {
console.log(entries)
// TODO...
}, options)
接收两个参数 callback
和 options
,回调函数中参数 entries
是 IntersectionObserverEntry
实例。描述了 目标元素
与 root
的交叉状态。
回调函数
属性 | 描述 |
---|---|
boundingClientRect | 返回包含目标元素的边界信息,返回结果与 element.getBoundingClientRect() 相同 |
intersectionRatio | 返回目标元素出现在可视区的比例 |
intersectionRect | 用来描述 root 和目标元素的相交区域 |
isIntersecting | 返回一个布尔值。1. 如果目标元素出现在 root 可视区,返回 true。2. 如果从 root 可视区消失,返回 false |
rootBounds | 用来描述交叉区域观察者(intersection observer)中的根. |
target | 目标元素:与根出现相交区域改变的元素 (Element) |
time | 返回一个记录从 IntersectionObserver 的时间原点到交叉被触发的时间的时间戳 |
注意:表格中加粗的属性是比较常用的判断条件
options 选项
options 是一个对象,可选参数:
属性 | 描述 |
---|---|
root | 所监听对象的具体祖先元素。如果未传入值或值为 null,则默认使用顶级文档的视窗(一般为 html) |
rootMargin | 计算交叉时添加到根(root)边界盒 bounding box 的矩形偏移量, 可以有效的缩小或扩大根的判定范围从而满足计算需要。所有的偏移量均可用像素(px)或百分比(%)来表达, 默认值为"0px 0px 0px 0px" |
threshold | 一个包含阈值的列表, 按升序排列, 列表中的每个阈值都是监听对象的交叉区域与边界区域的比率。当监听对象的任何阈值被越过时,都会触发 callback。默认值为 0 |
实例方法
属性 | 描述 |
---|---|
observe() | 开始监听一个目标元素 |
unobserve() | 停止监听特定目标元素 |
takeRecords() | 返回所有观察目标的 IntersectionObserverEntry 对象数组 |
disconnect() | 使 IntersectionObserver 对象停止全部监听工作 |
应用场景:
- 图片懒加载
- 埋点曝光
- 滚动动画
MutationObserver
它可以监听对元素的属性的修改、对它的子节点的增删改
用法
var observer = new MutationObserver(callback)
/*
*观察者回调
*records:变化记录数组
*instance:观察者对象本身
*/
const callback = (records, instance) => {
console.log(records)
console.log(instance)
records.map((record) => {
console.log('Mutation Type: ' + record.type)
console.log('Mutation Change Attribute: ' + record.attributeName)
console.log('Previous attribute value: ' + record.oldValue)
})
}
observer = new MutationObserver(callback)
callback
,即回调函数接收两个参数,第一个参数是一个包含了所有 MutationRecord
对象的数组,第二个参数则是这个 MutationObserver
实例本身。
Mutation 事件列表
名称 | 描述 |
---|---|
DOMAttrModified | 节点属性变更 |
DOMAttributeNameChanged | 节点属性属性节点名字改变 |
DOMCharacterDataModified | 节点中的文本节点改变 |
DOMElementNameChanged | 节点移除 |
DOMNodeInserted | 节点子节点插入 |
DOMNodeRemoved | 节点子节点移除 |
DOMNodeInsertedIntoDocument | 节点插入文档 |
DOMSubtreeModified | 节点子节点修改 |
观察者 observe
//观察者配置项
var options = {
childList: true, //观察目标节点的子节点的新增和删除
subtree: true, //观察目标节点的所有后代节点
attributes: true, //观察目标节点的属性节点
attributeOldValue: true, //在attributes属性已经设为true的前提下, 将发生变化的属性节点之前的属性值记录下来
attributeFilter: [], //一个属性名数组(不需要指定命名空间),只有该数组中包含的属性名发生变化时才会被观察到,其他名称的属性发生变化后会被忽略想要设置那些删选参数的话
characterData: true, //如果目标节点为characterData节点(一种抽象接口,具体可以为文本节点,注释节点,以及处理指令节点)时,也要观察该节点的文本内容是否发生变化
characterDataOldValue: true, //在characterData属性已经设为true的前提下,将发生变化characterData节点之前的文本内容记录下来(记录到下面MutationRecord对象的oldValue属性中)
}
//待观察的DOM节点
var element = document.getElementById('text')
//执行观察
observer.observe(element, options)
实例方法
名称 | 描述 |
---|---|
disconnect() | 停止观察 |
takeRecords() | 清除变动记录 |
应用场景
Vue 源码
里尝试使用mutationObserver
来做降级
PerformanceObserver
ResizeObserver
问题:窗口我们可以用 addEventListener
监听 resize
事件,那元素呢?
元素可以用 ResizeObserver
监听大小的改变,当 width
、height
被修改时会触发回调。也可以做 echarts
图表自适应
用法
const box = document.querySelector('#box')
setTimeout(() => {
box.style.width = '200px'
}, 1000)
const resizeObserver = new ResizeObserver((entries) => {
console.log('当前大小', entries)
})
resizeObserver.observe(box)
可以拿到元素和它的位置、尺寸。这样我们就实现了对元素的 resize
的监听。