Open FrankKai opened 4 years ago
var observer = new IntersectionObserver(callback[, options]);
下面的例子在threshold值变化在10%以上时触发myObserverCallback。
let observer = new IntersectionObserver(myObserverCallback, { "threshold": 0.1 });
<template>
<div>
<img v-for="(image, i) in images" :key="i" src :data-img-url="image" />
</div>
</template>
<script>
export default {
data() {
return {
images: [
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247890587&di=88d4066be3d57ac962a6bec37e265d37&imgtype=0&src=http%3A%2F%2F01.imgmini.eastday.com%2Fmobile%2F20170810%2F20170810151144_d41d8cd98f00b204e9800998ecf8427e_3.jpeg',
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4054762707,1853885380&fm=26&gp=0.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247912077&di=508a949e5e291875debf6ca844292cd4&imgtype=0&src=http%3A%2F%2F03imgmini.eastday.com%2Fmobile%2F20180827%2F20180827095359_6759372e9bd28026ee6f53b500fb4291_2.jpeg',
],
};
},
mounted() {
const images = document.querySelectorAll('img');
const observerLazyLoad = new IntersectionObserver((entries) => {
entries.forEach((item) => {
if (item.isIntersecting) {
item.target.src = item.target.dataset.imgUrl;
}
});
});
images.forEach((image) => {
observerLazyLoad.observe(image);
});
},
};
</script>
<style lang="scss" scoped>
img {
display: block;
height: 500px;
margin: 30px;
}
</style>
<template>
<div>
<p class="fixed-top-helper"></p>
<p class="fixed-top-reference"></p>
<header>头部</header>
<main>
<img v-for="(image, i) in images" :key="i" :src="image" />
</main>
</div>
</template>
<script>
export default {
data() {
return {
images: [
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247890587&di=88d4066be3d57ac962a6bec37e265d37&imgtype=0&src=http%3A%2F%2F01.imgmini.eastday.com%2Fmobile%2F20170810%2F20170810151144_d41d8cd98f00b204e9800998ecf8427e_3.jpeg',
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4054762707,1853885380&fm=26&gp=0.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247912077&di=508a949e5e291875debf6ca844292cd4&imgtype=0&src=http%3A%2F%2F03imgmini.eastday.com%2Fmobile%2F20180827%2F20180827095359_6759372e9bd28026ee6f53b500fb4291_2.jpeg',
],
};
},
mounted() {
const header = document.querySelector('header');
const fixedTopReference = document.querySelector('.fixed-top-reference');
fixedTopReference.style.top = `${header.offsetTop}px`;
const observerFixedTop = new IntersectionObserver((entries) => {
entries.forEach((item) => {
if (item.boundingClientRect.top < 0) {
header.classList.add('fixed');
} else {
header.classList.remove('fixed');
}
});
});
observerFixedTop.observe(fixedTopReference);
},
};
</script>
<style lang="scss" scoped>
.fixed-top-helper {
height: 1px;
background: #ccc;
}
header {
background: #ccc;
&.fixed {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
}
main {
img {
display: block;
height: 500px;
margin: 30px;
}
}
</style>
注意事项:
<template>
<div>
<main>
<img v-for="(image, i) in images" :key="i" src="image" />
</main>
<footer>底部</footer>
</div>
</template>
<script>
export default {
data() {
return {
images: [
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247890587&di=88d4066be3d57ac962a6bec37e265d37&imgtype=0&src=http%3A%2F%2F01.imgmini.eastday.com%2Fmobile%2F20170810%2F20170810151144_d41d8cd98f00b204e9800998ecf8427e_3.jpeg',
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4054762707,1853885380&fm=26&gp=0.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247912077&di=508a949e5e291875debf6ca844292cd4&imgtype=0&src=http%3A%2F%2F03imgmini.eastday.com%2Fmobile%2F20180827%2F20180827095359_6759372e9bd28026ee6f53b500fb4291_2.jpeg',
],
};
},
mounted() {
const footer = document.querySelector('footer');
const observerTouchBottom = new IntersectionObserver((entries) => {
entries.forEach((item) => {
if (item.isIntersecting) {
setTimeout(() => {
console.log('滚动到了底部,可以发request请求数据了');
}, 2000);
}
});
});
observerTouchBottom.observe(footer);
},
};
</script>
<style lang="scss" scoped>
main {
img {
display: block;
height: 500px;
margin: 30px;
}
}
footer {
background: #ccc;
}
</style>
上面的例子是为了脱离框架更好的揭示IntersectionObserver的用法本质,如果在实际项目中使用,还需要考虑一些其他问题。
考虑内容如下:
<template>
<div>
<p class="fixed-top-helper"></p>
<p class="fixed-top-reference"></p>
<header>头部</header>
<main>
<img v-for="(image, i) in images" :key="i" src :data-img-url="image" />
</main>
<footer>底部</footer>
</div>
</template>
<script>
const images = [
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247890587&di=88d4066be3d57ac962a6bec37e265d37&imgtype=0&src=http%3A%2F%2F01.imgmini.eastday.com%2Fmobile%2F20170810%2F20170810151144_d41d8cd98f00b204e9800998ecf8427e_3.jpeg',
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4054762707,1853885380&fm=26&gp=0.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574247912077&di=508a949e5e291875debf6ca844292cd4&imgtype=0&src=http%3A%2F%2F03imgmini.eastday.com%2Fmobile%2F20180827%2F20180827095359_6759372e9bd28026ee6f53b500fb4291_2.jpeg',
];
export default {
data() {
return {
images,
lazyLoad: {
target: null,
observer: null,
},
touchFooter: {
target: null,
observer: null,
},
stickHeader: {
target: null,
reference: null,
observer: null,
},
};
},
mounted() {
this.createLazyLoadObserver();
this.createTouchFooterObserver();
this.createStickHeaderObserver();
},
beforeDestroy() {
this.unobserveAllIntersectionObservers();
},
methods: {
/*
* 创建懒加载observer并遍历监听所有img
*/
createLazyLoadObserver() {
this.lazyLoad.target = document.querySelectorAll('img');
this.lazyLoad.observer = new IntersectionObserver((entries) => {
entries.forEach((item) => {
if (item.isIntersecting) {
item.target.src = item.target.dataset.imgUrl;
}
});
});
this.lazyLoad.target.forEach((image) => {
this.lazyLoad.observer.observe(image);
});
},
/*
* 创建触底observer并监听footer
*/
createTouchFooterObserver() {
this.touchFooter.target = document.querySelector('footer');
this.touchFooter.observer = new IntersectionObserver((entries) => {
entries.forEach((item) => {
if (item.isIntersecting) {
setTimeout(() => {
console.log('滚动到了底部,可以发request请求数据了');
}, 2000);
}
});
});
this.touchFooter.observer.observe(this.touchFooter.target);
},
/*
* 创建吸顶observer并监听header
* 创建reference首次防抖,.fixed-top-helper二次防抖
*/
createStickHeaderObserver() {
this.stickHeader.target = document.querySelector('header');
this.stickHeader.reference = document.querySelector('.fixed-top-reference');
this.stickHeader.reference.style.top = `${this.stickHeader.target.offsetTop}px`;
this.stickHeader.observer = new IntersectionObserver((entries) => {
entries.forEach((item) => {
if (item.boundingClientRect.top < 0) {
this.stickHeader.target.classList.add('fixed');
} else {
this.stickHeader.target.classList.remove('fixed');
}
});
});
this.stickHeader.observer.observe(this.stickHeader.reference);
},
/*
* 取消observe所有监听目标
*/
unobserveAllIntersectionObservers() {
/*
* disconncet()可以取消所有observed目标
* 如果调用unobserve取消监听,稍显冗余的代码如下:
this.lazyLoad.target.forEach((image) => {
this.lazyLoad.observer.unobserve(image);
});
*/
this.lazyLoad.observer.disconnect();
/*
* 由于touchFooter和stickHeader只observe了一个目标,因此单独unobserve即可
* 当然disconnect()也是ok的
*/
this.touchFooter.observer.unobserve(this.touchFooter.target);
this.stickHeader.observer.unobserve(this.stickHeader.reference);
},
},
};
</script>
<style lang="scss" scoped>
.fixed-top-helper {
height: 1px;
background: #ccc;
}
header {
background: #ccc;
&.fixed {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
}
main {
img {
display: block;
height: 500px;
margin: 30px;
}
}
footer {
background: #ccc;
}
</style>
官方提供了Basic Process,Progress,Sticky Side,Sticky Overlay几种示例。
在项目中可以当做适当引用。
项目地址:https://github.com/russellgoldenberg/scrollama demo地址:https://russellgoldenberg.github.io/scrollama/basic/
https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API/Timing_element_visibility https://juejin.im/post/5ca15c1e51882567b544ee0b https://medium.com/walmartlabs/lazy-loading-images-intersectionobserver-8c5bff730920 https://juejin.im/post/5d665133e51d4561c83e7c83 https://github.com/russellgoldenberg/scrollama