整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          滾動(dòng)到可視窗口區(qū)域

          滾動(dòng)到可視窗口區(qū)域
          // 定制詳情頁(yè)之選擇欄目
          $(document).off('click','.js-nav-headerwrap>a').on('click','.js-nav-headerwrap>a',function(){
              var _$this=$(this);
              _$this.addClass('active').siblings().removeClass('active');
              $('.cs-custommade').removeClass('isactive');
              if (_$this.attr('data-set')) {
                  $('.'+ _$this.attr('data-set')).addClass('isactive');
              } 
              //如果固定
              if ($('.js-nav-headerwrap').hasClass('fixed')) {
                  var scrollTop=$(window).scrollTop();
                  var numTop=$('.apply-main').height() + $('.courser-info-second').height()+  $('.course-studytime-new22').height();
                  console.log(numTop);
                // 距離
                  $("body,html").animate({
                      scrollTop: numTop 
                  }, 300);
              }
              
          });


          可視區(qū)域即我們?yōu)g覽網(wǎng)頁(yè)的設(shè)備肉眼可見(jiàn)的區(qū)域,如下圖

          在日常開(kāi)發(fā)中,我們經(jīng)常需要判斷目標(biāo)元素是否在視窗之內(nèi)或者和視窗的距離小于一個(gè)值(例如 100 px),從而實(shí)現(xiàn)一些常用的功能,例如:

          • 圖片的懶加載
          • 列表的無(wú)限滾動(dòng)
          • 計(jì)算廣告元素的曝光情況
          • 可點(diǎn)擊鏈接的預(yù)加載

          實(shí)現(xiàn)方式

          判斷一個(gè)元素是否在可視區(qū)域,我們常用的有三種辦法:

          • offsetTop、scrollTop
          • getBoundingClientRect
          • Intersection Observer

          offsetTop、scrollTop

          offsetTop,元素的上外邊框至包含元素的上內(nèi)邊框之間的像素距離,其他offset屬性如下圖所示:

          下面再來(lái)了解下clientWidthclientHeight

          • clientWidth:元素內(nèi)容區(qū)寬度加上左右內(nèi)邊距寬度,即clientWidth=content + padding
          • clientHeight:元素內(nèi)容區(qū)高度加上上下內(nèi)邊距高度,即clientHeight=content + padding

          這里可以看到client元素都不包括外邊距

          最后,關(guān)于scroll系列的屬性如下:

          • scrollWidthscrollHeight 主要用于確定元素內(nèi)容的實(shí)際大小
          • scrollLeftscrollTop 屬性既可以確定元素當(dāng)前滾動(dòng)的狀態(tài),也可以設(shè)置元素的滾動(dòng)位置
          • 垂直滾動(dòng) scrollTop > 0水平滾動(dòng) scrollLeft > 0
          • 將元素的 scrollLeftscrollTop 設(shè)置為 0,可以重置元素的滾動(dòng)位置

          注意

          • 上述屬性都是只讀的,每次訪問(wèn)都要重新開(kāi)始

          下面再看看如何實(shí)現(xiàn)判斷:

          公式如下:

          el.offsetTop - document.documentElement.scrollTop <=viewPortHeight

          代碼實(shí)現(xiàn):

          function isInViewPortOfOne (el) {
              // viewPortHeight 兼容所有瀏覽器寫法
              const viewPortHeight=window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 
              const offsetTop=el.offsetTop
              const scrollTop=document.documentElement.scrollTop
              const top=offsetTop - scrollTop
              return top <=viewPortHeight
          }

          getBoundingClientRect

          rectObject.top:元素上邊到視窗上邊的距離;
          rectObject.right:元素右邊到視窗左邊的距離;
          rectObject.bottom:元素下邊到視窗上邊的距離;
          rectObject.left:元素左邊到視窗左邊的距離;
          rectObject.width:是元素自身的寬度
          rectObject.height是元素自身的高度

          getBoundingClientRect()獲取元素位置,這個(gè)方法沒(méi)有參數(shù)

          getBoundingClientRect用于獲得頁(yè)面中某個(gè)元素的左,上,右和下分別相對(duì)瀏覽器視窗的位置。
          getBoundingClientRect是DOM元素到瀏覽器可視范圍的距離(不包含文檔卷起的部分)。
          該函數(shù)返回一個(gè)Object對(duì)象,該對(duì)象有6個(gè)屬性:top,lef,right,bottom,width,height;

          • width、height是元素自身的寬高
          • right是指元素右邊界距窗口最左邊的距離,bottom是指元素下邊界距窗口最上面的距離
          document.body.getBoundingClientRect().width

          返回值是一個(gè) DOMRect對(duì)象,擁有left, top, right, bottom, x, y, width, 和 height屬性

          const target=document.querySelector('.target');
          const clientRect=target.getBoundingClientRect();
          console.log(clientRect);
          
          // {
          //   bottom: 556.21875,
          //   height: 393.59375,
          //   left: 333,
          //   right: 1017,
          //   top: 162.625,
          //   width: 684
          // }
          

          屬性對(duì)應(yīng)的關(guān)系圖如下所示:

          當(dāng)頁(yè)面發(fā)生滾動(dòng)的時(shí)候,topleft屬性值都會(huì)隨之改變

          如果一個(gè)元素在視窗之內(nèi)的話,那么它一定滿足下面四個(gè)條件:

          • top 大于等于 0
          • left 大于等于 0
          • bottom 小于等于視窗高度
          • right 小于等于視窗寬度

          實(shí)現(xiàn)代碼如下:

          function isInViewPort(element) {
            const viewWidth=window.innerWidth || document.documentElement.clientWidth;
            const viewHeight=window.innerHeight || document.documentElement.clientHeight;
            const {
              top,
              right,
              bottom,
              left,
            }=element.getBoundingClientRect();
          
            return (
              top >=0 &&
              left >=0 &&
              right <=viewWidth &&
              bottom <=viewHeight
            );
          }

          Intersection Observer

          Interp ObserverAPI是什么

          我們需要觀察的元素被稱為 目標(biāo)元素(target),設(shè)備視窗或者其他指定的元素視口的邊界框我們稱它為 根元素(root),或者簡(jiǎn)稱為

          Interp Observer API 翻譯過(guò)來(lái)叫做 “交叉觀察器”,因?yàn)榕袛嘣厥欠窨梢?jiàn)(通常情況下)的本質(zhì)就是判斷目標(biāo)元素和根元素是不是產(chǎn)生了 交叉區(qū)域

          為什么是通常情況下,因?yàn)楫?dāng)我們 css 設(shè)置了 opacity: 0,visibility: hidden 或者 用其他的元素覆蓋目標(biāo)元素 的時(shí)候,對(duì)于視圖來(lái)說(shuō)是不可見(jiàn)的,但對(duì)于交叉觀察器來(lái)說(shuō)是可見(jiàn)的。這里可能有點(diǎn)抽象,大家只需記住,交叉觀察器只關(guān)心 目標(biāo)元素根元素 是否有 交叉區(qū)域, 而不管視覺(jué)上能不能看見(jiàn)這個(gè)元素。當(dāng)然如果設(shè)置了 display:none,那么交叉觀察器就不會(huì)生效了,其實(shí)也很好理解,因?yàn)樵匾呀?jīng)不存在了,那么也就監(jiān)測(cè)不到了。

          一句話總結(jié):Interp Observer API 提供了一種異步檢測(cè)目標(biāo)元素與祖先元素或 viewport 相交情況變化的方法。 -- MDN

          現(xiàn)在不懂沒(méi)關(guān)系,咱們接著往下看,看完自然就明白了。

          Interp Observer API 怎么玩

          生成觀察器

          // 調(diào)用構(gòu)造函數(shù) InterpObserver 生成觀察器
          const myObserver=new InterpObserver(callback, options);  

          首先調(diào)用瀏覽器原生構(gòu)造函數(shù) InterpObserver ,構(gòu)造函數(shù)的返回值是一個(gè) 觀察器實(shí)例

          構(gòu)造函數(shù) InterpObserver 接收兩個(gè)參數(shù)

          • callback: 可見(jiàn)性發(fā)生變化時(shí)觸發(fā)的回調(diào)函數(shù)
          • options: 配置對(duì)象(可選,不傳時(shí)會(huì)使用默認(rèn)配置)

          使用步驟主要分為兩步:創(chuàng)建觀察者和傳入被觀察者

          構(gòu)造函數(shù)接收的參數(shù) options

          為了方便理解,我們先看第二個(gè)參數(shù) options 。一個(gè)可以用來(lái)配置觀察器實(shí)例的對(duì)象,那么這個(gè)配置對(duì)象都包含哪些屬性呢?

          • root: 設(shè)置目標(biāo)元素的根元素,也就是我們用來(lái)判斷元素是否可見(jiàn)的區(qū)域,必須是目標(biāo)元素的父級(jí)元素,如果不指定的話,則使用瀏覽器視窗,也就是 document。
          • rootMargin: 一個(gè)在計(jì)算交叉值時(shí)添加至根的邊界中的一組偏移量,類型為字符串 (string) ,可以有效的縮小或擴(kuò)大根的判定范圍從而滿足計(jì)算需要。語(yǔ)法大致和CSS 中 margin 屬性等同,默認(rèn)值 “0px 0px 0px 0px” ,如果有指定 root 參數(shù),則 rootMargin 也可以使用百分比來(lái)取值。
          • threshold: 介于 0 和 1 之間的數(shù)字,指示觸發(fā)前應(yīng)可見(jiàn)的百分比。也可以是一個(gè)數(shù)字?jǐn)?shù)組,以創(chuàng)建多個(gè)觸發(fā)點(diǎn),也被稱之為 閾值。如果構(gòu)造器未傳入值, 則默認(rèn)值為 0 。
          • trackVisibility: 一個(gè)布爾值,指示當(dāng)前觀察器是否將跟蹤目標(biāo)可見(jiàn)性的更改,默認(rèn)為 false ,注意,此處的可見(jiàn)性并非指目標(biāo)元素和根元素是否相交,而是指視圖上是否可見(jiàn),這個(gè)我們之前就已經(jīng)分析過(guò)了,如果此值設(shè)置為 false 或不設(shè)置,那么回調(diào)函數(shù)參數(shù)中 InterpObserverEntry 的 isVisible 屬性將永遠(yuǎn)返回 false 。
          • delay: 一個(gè)數(shù)字,也就是回調(diào)函數(shù)執(zhí)行的延遲時(shí)間(毫秒)。如果 trackVisibility 設(shè)置為 true,則此值必須至少設(shè)置為 100 ,否則會(huì)報(bào)錯(cuò)(但是這里我也只是親測(cè)出來(lái)的,并不知道為什么會(huì)設(shè)計(jì)成這樣,如果有大佬了解請(qǐng)指教一下)。

          創(chuàng)建觀察者

          const options={
            // 表示重疊面積占被觀察者的比例,從 0 - 1 取值,
            // 1 表示完全被包含
            threshold: 1.0, 
            root:document.querySelector('#scrollArea') // 必須是目標(biāo)元素的父級(jí)元素
          };
          
          const callback=(entries, observer)=> { ....}
          
          const observer=new IntersectionObserver(callback, options);

          通過(guò)new IntersectionObserver創(chuàng)建了觀察者 observer,傳入的參數(shù) callback 在重疊比例超過(guò) threshold 時(shí)會(huì)被執(zhí)行`

          關(guān)于callback回調(diào)函數(shù)常用屬性如下:

          // 上段代碼中被省略的 callback
          const callback=function(entries, observer) { 
              entries.forEach(entry=> {
                  entry.time;               // 觸發(fā)的時(shí)間
                  entry.rootBounds;         // 根元素的位置矩形,這種情況下為視窗位置
                  entry.boundingClientRect; // 被觀察者的位置舉行
                  entry.intersectionRect;   // 重疊區(qū)域的位置矩形
                  entry.intersectionRatio;  // 重疊區(qū)域占被觀察者面積的比例(被觀察者不是矩形時(shí)也按照矩形計(jì)算)
                  entry.target;             // 被觀察者
              });
          };

          傳入被觀察者

          通過(guò) observer.observe(target) 這一行代碼即可簡(jiǎn)單的注冊(cè)被觀察者

          const target=document.querySelector('.target');
          observer.observe(target);

          案例分析

          實(shí)現(xiàn):創(chuàng)建了一個(gè)十萬(wàn)個(gè)節(jié)點(diǎn)的長(zhǎng)列表,當(dāng)節(jié)點(diǎn)滾入到視窗中時(shí),背景就會(huì)從紅色變?yōu)辄S色

          Html結(jié)構(gòu)如下:

          <div class="container"></div>

          css樣式如下:

          .container {
              display: flex;
              flex-wrap: wrap;
          }
          .target {
              margin: 5px;
              width: 20px;
              height: 20px;
              background: red;
          }

          container插入1000個(gè)元素

          const $container=$(".container");
          
          // 插入 100000 個(gè) <div class="target"></div>
          function createTargets() {
            const htmlString=new Array(100000)
              .fill('<div class="target"></div>')
              .join("");
            $container.html(htmlString);
          }

          這里,首先使用getBoundingClientRect方法進(jìn)行判斷元素是否在可視區(qū)域

          function isInViewPort(element) {
              const viewWidth=window.innerWidth || document.documentElement.clientWidth;
              const viewHeight=  window.innerHeight || document.documentElement.clientHeight;
              const { top, right, bottom, left }=element.getBoundingClientRect();
          
              return top >=0 && left >=0 && right <=viewWidth && bottom <=viewHeight;
          }

          然后開(kāi)始監(jiān)聽(tīng)scroll事件,判斷頁(yè)面上哪些元素在可視區(qū)域中,如果在可視區(qū)域中則將背景顏色設(shè)置為yellow

          $(window).on("scroll", ()=> {
              console.log("scroll !");
              $targets.each((index, element)=> {
                  if (isInViewPort(element)) {
                      $(element).css("background-color", "yellow");
                  }
              });
          });

          通過(guò)上述方式,可以看到可視區(qū)域顏色會(huì)變成黃色了,但是可以明顯看到有卡頓的現(xiàn)象,原因在于我們綁定了scroll事件,scroll事件伴隨了大量的計(jì)算,會(huì)造成資源方面的浪費(fèi)

          下面通過(guò)Intersection Observer的形式同樣實(shí)現(xiàn)相同的功能

          首先創(chuàng)建一個(gè)觀察者

          const observer=new IntersectionObserver(getYellow, { threshold: 1.0 });

          getYellow回調(diào)函數(shù)實(shí)現(xiàn)對(duì)背景顏色改變,如下:

          function getYellow(entries, observer) {
              entries.forEach(entry=> {
                  $(entry.target).css("background-color", "yellow");
              });
          }

          最后傳入觀察者,即.target元素

          $targets.each((index, element)=> {
              observer.observe(element);
          });

          可以看到功能同樣完成,并且頁(yè)面不會(huì)出現(xiàn)卡頓的情況

          給大家分享我收集整理的各種學(xué)習(xí)資料,前端小白交學(xué)習(xí)流程,入門教程等回答-下面是學(xué)習(xí)資料參考。

          前端學(xué)習(xí)交流、自學(xué)、學(xué)習(xí)資料等推薦 - 知乎


          加載


          什么是懶加載

          懶加載其實(shí)就是延遲加載,是一種對(duì)網(wǎng)頁(yè)性能優(yōu)化可方式,比如當(dāng)訪問(wèn)一個(gè)頁(yè)面的時(shí)候,優(yōu)先顯示可視區(qū)域的圖片而不一次性加載所有圖片,當(dāng)需要顯示的時(shí)候再發(fā)送圖片請(qǐng)求,避免打開(kāi)網(wǎng)頁(yè)時(shí)加載過(guò)多資源。

          什么時(shí)候用懶加載

          當(dāng)頁(yè)面中需要一次性載入很多圖片的時(shí)候,往往都是需要用懶加載的。

          懶加載原理

          我們都知道HTML中的 <img>標(biāo)簽是代表文檔中的一個(gè)圖像。。說(shuō)了個(gè)廢話。。

          <img>標(biāo)簽有一個(gè)屬性是 src,用來(lái)表示圖像的URL,當(dāng)這個(gè)屬性的值不為空時(shí),瀏覽器就會(huì)根據(jù)這個(gè)值發(fā)送請(qǐng)求。如果沒(méi)有 src屬性,就不會(huì)發(fā)送請(qǐng)求。

          嗯?貌似這點(diǎn)可以利用一下?

          我先不設(shè)置 src,需要的時(shí)候再設(shè)置?

          nice,就是這樣。

          我們先不給 <img>設(shè)置 src,把圖片真正的URL放在另一個(gè)屬性 data-src中,在需要的時(shí)候也就是圖片進(jìn)入可視區(qū)域的之前,將URL取出放到 src中。

          實(shí)現(xiàn)


          HTML結(jié)構(gòu)

          <div class="container">
           <div class="img-area">
             <img class="my-photo" alt="loading" data-src="./img/img1.png">
           </div>
           <div class="img-area">
             <img class="my-photo" alt="loading" data-src="./img/img2.png">
           </div>
           <div class="img-area">
             <img class="my-photo" alt="loading" data-src="./img/img3.png">
           </div>
           <div class="img-area">
             <img class="my-photo" alt="loading" data-src="./img/img4.png">
           </div>
           <div class="img-area">
             <img class="my-photo" alt="loading" data-src="./img/img5.png">
           </div>
          </div>

          仔細(xì)觀察一下, <img>標(biāo)簽此時(shí)是沒(méi)有 src屬性的,只有 alt和 data-src屬性。

          alt 屬性是一個(gè)必需的屬性,它規(guī)定在圖像無(wú)法顯示時(shí)的替代文本。 data-* 全局屬性:構(gòu)成一類名稱為自定義數(shù)據(jù)屬性的屬性,可以通過(guò) HTMLElement.dataset來(lái)訪問(wèn)。

          如何判斷元素是否在可視區(qū)域

          方法一

          網(wǎng)上看到好多這種方法,稍微記錄一下。

          1. 通過(guò) document.documentElement.clientHeight獲取屏幕可視窗口高度
          2. 通過(guò) document.documentElement.scrollTop獲取瀏覽器窗口頂部與文檔頂部之間的距離,也就是滾動(dòng)條滾動(dòng)的距離
          3. 通過(guò) element.offsetTop獲取元素相對(duì)于文檔頂部的距離

          然后判斷②-③<①是否成立,如果成立,元素就在可視區(qū)域內(nèi)。

          方法二(推薦)

          通過(guò) getBoundingClientRect()方法來(lái)獲取元素的大小以及位置,MDN上是這樣描述的:

          The Element.getBoundingClientRect() method returns the size of an element and its position relative to the viewport.

          這個(gè)方法返回一個(gè)名為 ClientRect的 DOMRect對(duì)象,包含了 top、 right、 botton、 left、 width、 height這些值。

          MDN上有這樣一張圖:

          可以看出返回的元素位置是相對(duì)于左上角而言的,而不是邊距。

          我們思考一下,什么情況下圖片進(jìn)入可視區(qū)域。

          假設(shè) constbound=el.getBoundingClientRect();來(lái)表示圖片到可視區(qū)域頂部距離; 并設(shè) constclientHeight=window.innerHeight;來(lái)表示可視區(qū)域的高度。

          隨著滾動(dòng)條的向下滾動(dòng), bound.top會(huì)越來(lái)越小,也就是圖片到可視區(qū)域頂部的距離越來(lái)越小,當(dāng) bound.top===clientHeight時(shí),圖片的上沿應(yīng)該是位于可視區(qū)域下沿的位置的臨界點(diǎn),再滾動(dòng)一點(diǎn)點(diǎn),圖片就會(huì)進(jìn)入可視區(qū)域。

          也就是說(shuō),在 bound.top<=clientHeight時(shí),圖片是在可視區(qū)域內(nèi)的。

          我們這樣判斷:

          function isInSight(el) {
           const bound=el.getBoundingClientRect();
           const clientHeight=window.innerHeight;
           //如果只考慮向下滾動(dòng)加載
           //const clientWidth=window.innerWeight;
           return bound.top <=clientHeight + 100;
          }

          這里有個(gè)+100是為了提前加載。

          加載圖片

          頁(yè)面打開(kāi)時(shí)需要對(duì)所有圖片進(jìn)行檢查,是否在可視區(qū)域內(nèi),如果是就加載。

          function checkImgs() {
           const imgs=document.querySelectorAll('.my-photo');
           Array.from(imgs).forEach(el=> {
             if (isInSight(el)) {
               loadImg(el);
             }
           })
          }
          
          function loadImg(el) {
           if (!el.src) {
             const source=el.dataset.src;
             el.src=source;
           }
          }

          這里應(yīng)該是有一個(gè)優(yōu)化的地方,設(shè)一個(gè)標(biāo)識(shí)符標(biāo)識(shí)已經(jīng)加載圖片的index,當(dāng)滾動(dòng)條滾動(dòng)時(shí)就不需要遍歷所有的圖片,只需要遍歷未加載的圖片即可。

          函數(shù)節(jié)流

          在類似于滾動(dòng)條滾動(dòng)等頻繁的DOM操作時(shí),總會(huì)提到“函數(shù)節(jié)流、函數(shù)去抖”。

          所謂的函數(shù)節(jié)流,也就是讓一個(gè)函數(shù)不要執(zhí)行的太頻繁,減少一些過(guò)快的調(diào)用來(lái)節(jié)流。

          基本步驟:

          1. 獲取第一次觸發(fā)事件的時(shí)間戳
          2. 獲取第二次觸發(fā)事件的時(shí)間戳
          3. 時(shí)間差如果大于某個(gè)閾值就執(zhí)行事件,然后重置第一個(gè)時(shí)間
          function throttle(fn, mustRun=500) {
           const timer=null;
           let previous=null;
           return function() {
             const now=new Date();
             const context=this;
             const args=arguments;
             if (!previous){
               previous=now;
             }
             const remaining=now - previous;
             if (mustRun && remaining >=mustRun) {
               fn.apply(context, args);
               previous=now;
             }
           }
          }

          這里的 mustRun就是調(diào)用函數(shù)的時(shí)間間隔,無(wú)論多么頻繁的調(diào)用 fn,只有 remaining>=mustRun時(shí) fn才能被執(zhí)行。

          實(shí)驗(yàn)


          頁(yè)面打開(kāi)時(shí)

          可以看出此時(shí)僅僅是加載了img1和img2,其它的img都沒(méi)發(fā)送請(qǐng)求,看看此時(shí)的瀏覽器

          第一張圖片是完整的呈現(xiàn)了,第二張圖片剛進(jìn)入可視區(qū)域,后面的就看不到了~

          頁(yè)面滾動(dòng)時(shí)

          當(dāng)我向下滾動(dòng),此時(shí)瀏覽器是這樣

          此時(shí)第二張圖片完全顯示了,而第三張圖片顯示了一點(diǎn)點(diǎn),這時(shí)候我們看看請(qǐng)求情況

          img3的請(qǐng)求發(fā)出來(lái),而后面的請(qǐng)求還是沒(méi)發(fā)出~

          全部載入時(shí)

          當(dāng)滾動(dòng)條滾到最底下時(shí),全部請(qǐng)求都應(yīng)該是發(fā)出的,如圖

          更新


          方法三 IntersectionObserver

          經(jīng)大佬提醒,發(fā)現(xiàn)了這個(gè)方法

          先附上鏈接:

          jjc大大:

          https://github.com/justjavac/the-front-end-knowledge-you-may-dont-know/issues/10

          阮一峰大大:

          http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html

          API Sketch for Intersection Observers:

          https://github.com/WICG/IntersectionObserver

          IntersectionObserver可以自動(dòng)觀察元素是否在視口內(nèi)。

          var io=new IntersectionObserver(callback, option);
          // 開(kāi)始觀察
          io.observe(document.getElementById('example'));
          // 停止觀察
          io.unobserve(element);
          // 關(guān)閉觀察器
          io.disconnect();

          callback的參數(shù)是一個(gè)數(shù)組,每個(gè)數(shù)組都是一個(gè) IntersectionObserverEntry對(duì)象,包括以下屬性:

          屬性描述time可見(jiàn)性發(fā)生變化的時(shí)間,單位為毫秒rootBounds與getBoundingClientRect()方法的返回值一樣boundingClientRect目標(biāo)元素的矩形區(qū)域的信息intersectionRect目標(biāo)元素與視口(或根元素)的交叉區(qū)域的信息intersectionRatio目標(biāo)元素的可見(jiàn)比例,即intersectionRect占boundingClientRect的比例,完全可見(jiàn)時(shí)為1,完全不可見(jiàn)時(shí)小于等于0target被觀察的目標(biāo)元素,是一個(gè) DOM 節(jié)點(diǎn)對(duì)象

          我們需要用到 intersectionRatio來(lái)判斷是否在可視區(qū)域內(nèi),當(dāng) intersectionRatio>0&&intersectionRatio<=1即在可視區(qū)域內(nèi)。

          代碼

          function checkImgs() {
           const imgs=Array.from(document.querySelectorAll(".my-photo"));
           imgs.forEach(item=> io.observe(item));
          }
          
          function loadImg(el) {
           if (!el.src) {
             const source=el.dataset.src;
             el.src=source;
           }
          }
          
          const io=new IntersectionObserver(ioes=> {
           ioes.forEach(ioe=> {
             const el=ioe.target;
             const intersectionRatio=ioe.intersectionRatio;
             if (intersectionRatio > 0 && intersectionRatio <=1) {
               loadImg(el);
             }
             el.onload=el.onerror=()=> io.unobserve(el);
           });
          });

          源自:segmentfault

          聲明:文章著作權(quán)歸作者所有,如有侵權(quán),請(qǐng)聯(lián)系小編刪除。


          主站蜘蛛池模板: 成人国内精品久久久久一区| 久久综合亚洲色一区二区三区 | 国模视频一区二区| 亚洲一区二区三区乱码A| 一区二区三区在线观看| 91video国产一区| 国产一区在线视频| 精品国产一区二区三区www| 日本一区二区三区在线视频| 欧洲精品一区二区三区在线观看| 日韩精品一区二区三区在线观看| 精品无码国产一区二区三区51安| 理论亚洲区美一区二区三区| 久久婷婷色综合一区二区| 色综合视频一区二区三区44| 国产精品毛片一区二区| 国产在线精品一区二区中文| 国产成人精品一区二区三区无码| 欧洲精品无码一区二区三区在线播放 | 97精品国产一区二区三区| 视频一区二区在线播放| 一本大道在线无码一区| 91一区二区三区四区五区| 国产一区二区精品久久| 久久精品国产一区二区三区| 夜色阁亚洲一区二区三区| 日本视频一区二区三区| 国产成人一区二区三区电影网站 | 日韩精品一区二区三区老鸦窝| 一区二区三区四区在线播放| 国产精品第一区揄拍| 亚洲一区二区三区不卡在线播放| 色久综合网精品一区二区| 亚洲AV无码一区二区三区DV | 亚洲av无码片区一区二区三区| 一区二区在线视频免费观看| 精品国产一区二区三区www| 麻豆va一区二区三区久久浪| 成人精品一区久久久久| 国产成人av一区二区三区在线| 国产乱码精品一区三上|