一、IntersectionObserver API介绍:
1.概念
Intersection Observer API 提供 种异步观察 标元素与祖先元素或顶级 档viewport的交集中的变化的 法。
## 1.用法1. 新建observer实
const observer = new IntersectionObserver(callback, options);
callback:回调函数, 标元素的可 性发 变化时触发,参数为 IntersectionObserverEntry 对象的集合, 包含这个observer观察的所有 标元素中可 性变化的元素,每个元素对应 个 IntersectionObserverEntry。
IntersectionObserverEntry:描述 标元素与其根元素容 在某 特定过渡时刻的交叉状态。对象的属 性有:
- boundingClientRect: 同getBoundingClientRect()
- intersectionRatio: 标元素可视区内的部分与全部的 值
- intersectionRect: 标元素可视区内的部分
- isIntersecting: 是否进 可视区
- rootBounds: 根元素
- target: 标元素
- time: 从开始到触发回调的时间
options: observer 的配置选项:
- root: 于观察的根元素,需要是 个dom元素, 传或传null的时候默认为浏览 视
- rootMargin: 根元素的margin,margin区域算 可视区,(正margin增 ,负margin减 ),写法同css
-threshold: 进 可视区的阈值,进 可视区的 达到阈值时才触发回调,默认为0,可以传 个数
字或数组,传 数组时,每达到 个阈值触发 次 - isIntersecting: 是否进 可视区
2. 观察 标元素
const target = document.querySelector('#target');
observer.observe(target);
同 个observer可以观察多个元素,但 个元素只能同时被 个 observer 观察,后添加的会替换之前的 需 要观察时可以取消观察 标或取消 observer
observer.unobserve(target) // 取消观察target observer.disconnect() // 停 作
二、注意点
- rootMargin 为0时要加上px
- threshold为0且缓慢滚动时,intersectionRatio有时会有问题
- 根元素必须是 标元素的祖先元素
三、实例
1.懒加载
<template>
<div class="root">
<ul>
<li v-show="true" ref="li" v-for="(item, index) in list" :key="index">
{{index}}
</li>
</ul> </div>
</template>
const options = {
root: null,
rootMargin: '0px 0px -200px 0px',
threshold: 0
}
const observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.innerText = `${entry.target.innerText}----loaded`
observer.unobserve(entry.target)
} })
},
options )
const ul = this.$refs.li
// observer.observe(ul[0])
ul.forEach(li => {
observer.observe(li)
})
2. 限滚动(滚动加载)
<template>
<div class="root">
<ul>
<li v-show="true" ref="li" v-for="(item, index) in list" :key="index">
{{index}}
</li>
</ul>
<div class="trailer" ref="trailer" v-show="showTrailer"></div>
</div>
</template>
const trailerObserver = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
this.showTrailer = false
setTimeout(() => {
this.list.push(this.list.length)
this.showTrailer = true
}, 500)
} })
trailerObserver.observe(this.$refs.trailer)
tips:
- 标元素height为0并没有影响
- 切换 display: none 会触发回调函数