随着网页发展,对检测某个(些)元素是否出现在可视窗相关的需求越来越多了?比如:
当页面滚动时,懒加载图片或其他内容。
实现“可无限滚动”网站,也就是当用户滚动网页时直接加载更多内容,无需翻页。
对某些元素进行埋点曝光
滚动到相应区域来执行相应动画或其他任务。
一直以来,检测元素的可视状态或者两个元素的相对可视状态都不是件容易事,大部分解决办法并不完全可靠,实现方式很丑陋,也极易拖慢整个网站的性能。
IntersectionObserver正因此而生
reportDatail() 方法 对容器内容进行监听
如果dom 初始化存在 则在mounted() 进行监听即可;
如果 dom 是组件 是根据 请求返回的data 然后再渲染组件dom 则该方法使用在请求返回后
asiosDemo(){
...请求
if(success) {
this.list = data //返回的数据 然后list 对组件进行渲染
this.$nextTick(() => {
this.reportDatail()
})
}
}
methods:{
reportContent(index, name) {
console.log('曝光内容请求', index, name)
},
// 对dom 进行监听
reportDatail() {
// 容器dom
const dom = document.querySelector('.monitor-list')
setTimeout((_) => {
this.$_reportContent(
{
observeNodes: dom,
childNodes: dom.querySelectorAll('.content-task-item') // 监听子元素dom
},
// 回调函数 对返回的数据做埋点处理
this.reportContent
)
}, 0)
},
$_reportContent(options, callBackFn) {
// observeNodes 容器元素dom
// childNodes 被监听的曝光子元素dom
const { observeNodes, childNodes } = options
const io = new IntersectionObserver(
function(entrier) {
entrier.forEach((el, i) => {
if (el.isIntersecting) {
// _index _name 是子元素dom 创建的值
let _index = el.target.getAttribute('data-index')
let _name = el.target.getAttribute('data-name')
callBackFn(_index, _name)
// 监听的元素进行解绑
io.unobserve(el.target)
}
})
},
{
root: observeNodes,
rootMargin: '0px'
}
)
if (childNodes && childNodes.length !== 0) {
childNodes.forEach((el) => {
let _index = el.getAttribute('data-index') * 1
// this.exposureList记录最新的曝光内容 之前曝光过的不再监听
if (this.exposureList.includes(_index)) {
io.observe(el)
}
})
}
},
}