写在前面

今天碰到一个诉求,网页性能太慢,需要优化首屏加载速度。网页由10个视频资源,加10个图片资源构成,所有资源在同一时间加载(真不是我写的,我不接这个锅)。
立马想到的方案是,延迟加载,通过判断元素中心点的位置,来赋予src属性。同时要保证,视频超出视窗一半及暂停,反之则自动开始播放。毫无疑问,监听scroll事件来做了,scroll搭配setTimeout也还行,节流,功能也能实现。但是我觉得可以更好,一顿骚气搜索以后找到一个api Intersection observer,简直了,百分百契合我的诉求。

调试过程

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. <style>
  9. html,body{
  10. width: 100%;
  11. height: 100%;
  12. margin: 0;
  13. padding: 0;
  14. }
  15. .box{
  16. width: 100%;
  17. height: 100%;
  18. display: flex;
  19. flex-direction: column;
  20. align-content: center;
  21. align-items: center;
  22. justify-content: center;
  23. font-size: 50px;
  24. border: 1px solid red;
  25. box-sizing: border-box;
  26. margin: 10px 0;
  27. }
  28. </style>
  29. </head>
  30. <body>
  31. <div class="box" id="box1">1</div>
  32. <div class="box" id="box2">2</div>
  33. <div class="box" id="box3">3</div>
  34. <div class="box" id="box4">4</div>
  35. <div class="box" id="box5">5</div>
  36. </body>
  37. </html>
  1. var option ={
  2. root:null, // 你要监听的taget的父元素,不填为window
  3. threshold:0.5 // 可以理解为一个阈值,0-1,默认是0,就是只要露头就触发callback,1是完全显示才触发callback
  4. }
  5. var callback =function(entries,observer){
  6. // 这里的参数比较多,这里只需要isIntersecting
  7. //entires是一个数组,包含了每个监听对象的IntersectionObserverEntry
  8. //我们要用的是entry.isIntersecting
  9. //返回一个布尔值, 如果目标元素与交叉区域观察者对象(intersection observer) 的根相交,
  10. //则返回 true .如果返回 true, 则 IntersectionObserverEntry 描述了变换到交叉时的状态;
  11. //如果返回 false, 那么可以由此判断,变换是从交叉状态到非交叉状态.
  12. entries.forEach(function(entry){
  13. if(entry.isIntersecting) {
  14. // 露头了 搞事情,播放视频,src赋值什么的
  15. } else{
  16. //开溜了 ,暂停视频,节约资源
  17. }
  18. })
  19. }
  20. var target1 = document.querySelector('#box1');
  21. var target2 = document.querySelector('#box2');
  22. var target3 = document.querySelector('#box3');
  23. var target4 = document.querySelector('#box4');
  24. var target5 = document.querySelector('#box5');
  25. var observer = new IntersectionObserver(callback,option);
  26. observer.observe(target1);
  27. observer.observe(target2);
  28. observer.observe(target3);
  29. observer.observe(target4);
  30. observer.observe(target5);

IntersectionObserverEntry的详细解释可以点击链接去到MDN查看

IntersectionObserver其他方法

  • disconnect 使IntersectionObserver对象停止监听工作
  • takeRecords 返回所有观察目标的IntersectionObserverEntry对象数组
  • unobserver 使IntersectionObserver停止监听特定目标元素。

    小结

    以往的方法都是监听scroll再结合[getBoundingClientRect](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect),这个新的api可以省去很多东西,性能方面,肯定是比scroll监听要好,如果实现了你的目的,没有后续的,可以直接停止监听。