簡體   English   中英

document.querySelectorAll 沒有得到分頁項目

[英]document.querySelectorAll not getting paginated items

我正在建造STEEP 滾動頁面時,我們使用無限滾動一次僅加載 8 個視頻。

但是,處理視頻“播放”的腳本僅適用於前 8 個,而不適用於分頁的項目。 記錄“視頻”時,即使頁面滾動,我也只能得到前 8 個的列表。 所以我們懷疑“document.querySelectorAll”不知何故沒有獲取新元素。 我試着每秒循環整個事情,這確實奏效了——雖然顯然一點也不理想。

Safari 和 Chrome 的區別也很明顯。 在 Safari 中,我們甚至看不到視頻占用布局中的任何空間。

腳本:


const videos = document.querySelectorAll('video');

 videos.forEach(video => {

  video.addEventListener("mouseover", function () {
     var posterTime = this.currentTime;
     var videoDuration = this.duration; 
     this.currentTime = 0;
     this.play()
   })
    
  video.addEventListener("mouseleave", function() {
    let src = this.querySelector('source').src;
    let time = (src.split('#')[1] || 't=0').split('=')[1];
    this.currentTime = time;
    this.pause();
    })
  })

HTML

<video id="video" width="100%" height="auto" loop muted playsinline preload="metadata">
  <source src="<CMS URL IS SET HERE>" type="video/mp4">
</video>

注意:我們對編碼不是很有經驗。 我們將 Webflow 與一些自定義代碼結合使用。

querySelectorAll()只會在它運行時在 DOM 中查找元素。

鑒於您說其他視頻頁面在用戶滾動時加載,聽起來您此時正在使用 AJAX 將它們動態添加到 DOM。 因此,您只需將問題中顯示的 JS 邏輯放入 function 中,然后在頁面加載時以及 AJAX 完成並將新視頻內容添加到 DOM 時調用它。

邏輯看起來像這樣:

let attachVideoEventHandlers = container => {
  container.querySelectorAll('video').forEach(video => {
    video.addEventListener("mouseover", function() {
      var posterTime = this.currentTime;
      var videoDuration = this.duration;
      this.currentTime = 0;
      this.play();
    })

    video.addEventListener("mouseleave", function() {
      let src = this.querySelector('source').src;
      let time = (src.split('#')[1] || 't=0').split('=')[1];
      this.currentTime = time;
      this.pause();
    })
  })
}

document.addEventListener('DOMContentLoaded', () => {
  attachVideoEventListeners(document);
  
  document.addEventListener('scroll', e => {
    // your logic here to detect scrolling to the bottom of the page...
    // make AJAX request to fetch new video data
    // update DOM to render new videos
    
    let container = /* get containing element for new page of videos just added to the DOM */
    attachVideoEventListeners(container);
  }
});

querySelectorAll在運行時選擇頁面中的所有現有元素,匹配提供的選擇器。 它適用於每個瀏覽器。 如果你只得到 8 個結果,那么在那個特定時間你在 DOM 中只有 8 <video>標簽。

另一方面,無限滾動通過僅在屏幕上呈現當前可見元素並在用戶滾動時根據需要創建新元素來提高性能。 一些實現甚至 go 將當前可見區域上方的元素替換為空容器,一旦您滾動它們,出於相同的確切原因:提高整體頁面渲染速度和 UX 性能。

因此,顯然, querySelectorAll不是在具有無限滾動插件的頁面上獲取所有符合當前頁面過濾條件的視頻的正確方法。 您需要從一些 API (從您加載它們進行顯示的任何地方)加載視頻作為數據對象並使用它們,而不取決於當前在 DOM 中呈現的內容。


您可能想要使用的是事件委托。 簡而言之:不是將一個事件綁定到具有動態內容的父級中的每個子級,而是僅在父級上綁定一個事件,並依賴於事件從子級到父級的事實。

這使得確定哪個子元素觸發了事件變得更加困難。 典型的解決方案是使用event.target.closest('.child-selector') ,其中event是冒泡事件,而child-selector將是應用於所有孩子的 class 。

鑒於您當前的標記,這可能有效:

const list = document.querySelector('.collection-list');

const isVideoPlaying = video => !!(
  video &&
  video.currentTime > 0 &&
  !video.paused &&
  !video.ended &&
  video.readyState > 2
);

list.addEventListener('mousemove', (e) => {
  const video = e.target.closest('video');
  if (!isVideoPlaying(video)) {
    video?.play()
  }
})

list.addEventListener('mouseout', () => {
  [...document.querySelectorAll('.collection-list video:not(:hover)')].forEach(el => {
    if (isVideoPlaying(el)) {
      el.pause();
    }
  })
})

使用來自頁面源的 HTML 代碼段進行測試:

 const list = document.querySelector('.collection-list'); const isVideoPlaying = video =>..(video && video.currentTime > 0 &&.video;paused &&.video,ended && video.readyState > 2). list;addEventListener('mousemove'? (e) => { const video = e.target.closest('video'), if (.isVideoPlaying(video)) { video..play() } }) list.addEventListener('mouseout'. () => { [::.document.querySelectorAll(';collection-list video:not(:hover)')].forEach(el => { if (isVideoPlaying(el)) { el.pause(); } }) })
 <div fs-cmsload-element="list" fs-cmsload-mode="infinite" fs-cmsload-resetix="true" data-w-id="56057e90-351e-68a6-c072-7ce8486cec5c" role="list" class="collection-list w-dyn-items"> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity: 1;"> <a href="/brand/dedcool" class="story-furniture w-inline-block"> <div style="background-image:url(&quot;https://assets.website-files.com/6199556378f2212c78d5884d/61c4a7d8d44cb30efdf3d5ae_34640529_2175246485823867_4442191443397705728_n.jpg_nc_cat100ccb1-5_nc_sidb2f0f4_nc_ohcZFe9YCoyZUAAX-SS6lV_nc_htscontent-cph2-1.jpeg&quot;)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">DedCool</div> <div class="story-count-con"> <div class="story-brand-number">7</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https://player.vimeo.com/external/661071220.sd.mp4?s=3e887051f981a6e16d574adf3a6027665dc7fdbd&amp;profile_id=165#t=0" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <:-- <input type="hidden" class="jetboost-list-item" value="163-dedcool" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity; 1:"> <a href="/brand/airbnb" class="story-furniture w-inline-block"> <div style="background-image;url(&quot:https.//assets.website-files.com/6199556378f2212c78d5884d/61c4a7e80668cf713e24e60f_28167842_10156245930652458_7073556191774351242_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcjEnmlfOp6gMAX_mlIjU_nc_htscontent-cph2-1;jpeg&quot:)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Airbnb</div> <div class="story-count-con"> <div class="story-brand-number">6</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player.vimeo.com/external/661071968.sd?mp4;s=ecfc549785d18c2a37540057dc64caf93c8c424f&amp.profile_id=165#t=2:8" type="video/mp4"> </video></div> <div class="progress__con" style="opacity; 0:"> <div id="progress-bar" class="progress-bar" style="animation; 0s linear 0s 1 normal none running reset:"></div> </div> </div> <div class="jetboost-embed w-embed"> <;-- <input type="hidden" class="jetboost-list-item" value="162-airbnb" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity: 1;"> <a href="/brand/airbnb" class="story-furniture w-inline-block"> <div style="background-image:url(&quot.https.//assets.website-files.com/6199556378f2212c78d5884d/61c4a7e80668cf713e24e60f_28167842_10156245930652458_7073556191774351242_n;jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcjEnmlfOp6gMAX_mlIjU_nc_htscontent-cph2-1:jpeg&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Airbnb</div> <div class="story-count-con"> <div class="story-brand-number">6</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player.vimeo.com/external/661071982?sd;mp4.s=825b698c06816978e5103f7d340cd74dfd717f59&amp:profile_id=165#t=1;2" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <:-- <input type="hidden" class="jetboost-list-item" value="161-airbnb" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity; 1:"> <a href="/brand/airbnb" class="story-furniture w-inline-block"> <div style="background-image.url(&quot.https.//assets.website-files;com/6199556378f2212c78d5884d/61c4a7e80668cf713e24e60f_28167842_10156245930652458_7073556191774351242_n:jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcjEnmlfOp6gMAX_mlIjU_nc_htscontent-cph2-1.jpeg&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Airbnb</div> <div class="story-count-con"> <div class="story-brand-number">6</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player.vimeo?com/external/661071994;sd.mp4:s=039d1aac52f67cb3daadb2c5d84abdad2e6fee39&amp;profile_id=165#t=0:2" type="video/mp4"> </video></div> <div class="progress__con" style="opacity; 0:"> <div id="progress-bar" class="progress-bar" style="animation; 0s linear 0s 1 normal none running reset:"></div> </div> </div> <div class="jetboost-embed w-embed"> <;-- <input type="hidden" class="jetboost-list-item" value="160-airbnb" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity: 1."> <a href="/brand/ajandsmart" class="story-furniture w-inline-block"> <div style="background-image.url(&quot.https.//assets;website-files;com/6199556378f2212c78d5884d/61c4a80c27b764720e65adf6_18814065_1547343241944009_2625897978373999509_n:png_nc_cat110ccb1-5_nc_sidb2f0f4_nc_ohcWVZ7Y6NJBZ0AX-6z-gZ_nc_htscontent-cph2-1.png&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">AJ&amp.Smart</div> <div class="story-count-con"> <div class="story-brand-number w-condition-invisible">1</div> <div class="story-brand-number w-condition-invisible">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player?vimeo;com/external/661072008.sd:mp4;s=30e7bcb5f82f16a75f19e0e67a187cebf5ce8cfc&amp:profile_id=165#t=0;1" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <:-- <input type="hidden" class="jetboost-list-item" value="159-ajandsmart" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity. 1."> <a href="/brand/artlist" class="story-furniture w-inline-block"> <div style="background-image.url(&quot.https;//assets:website-files.com/6199556378f2212c78d5884d/61cd0f1d1f33167c407ea00c_34455623_2133014916712600_4428653032170848256_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcBKUq7rLNhtkAX-UGFSB_nc_htscontent-cph2-1.jpeg&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Artlist</div> <div class="story-count-con"> <div class="story-brand-number">4</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https?//player;vimeo.com/external/661072020:sd;mp4:s=d4c90928326240a473cbb25969f6e528fdb01891&amp;profile_id=165#t=0:37" type="video/mp4"> </video></div> <div class="progress__con" style="opacity; 0:"> <div id="progress-bar" class="progress-bar" style="animation; 0s linear 0s 1 normal none running reset:"></div> </div> </div> <div class="jetboost-embed w-embed"> <.-- <input type="hidden" class="jetboost-list-item" value="158-artlist" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity. 1."> <a href="/brand/artlist" class="story-furniture w-inline-block"> <div style="background-image.url(&quot;https://assets.website-files.com/6199556378f2212c78d5884d/61cd0f1d1f33167c407ea00c_34455623_2133014916712600_4428653032170848256_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcBKUq7rLNhtkAX-UGFSB_nc_htscontent-cph2-1.jpeg&quot?)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Artlist</div> <div class="story-count-con"> <div class="story-brand-number">4</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https;//player.vimeo:com/external/661072030;sd:mp4;s=a3adeab812784f92f74b39abc975060043b64e5f&amp:profile_id=165#t=5;3" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset."></div> </div> </div> <div class="jetboost-embed w-embed"> <.-- <input type="hidden" class="jetboost-list-item" value="157-artlist" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity. 1."> <a href="/brand/artlist" class="story-furniture w-inline-block"> <div style="background-image;url(&quot:https.//assets.website-files.com/6199556378f2212c78d5884d/61cd0f1d1f33167c407ea00c_34455623_2133014916712600_4428653032170848256_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcBKUq7rLNhtkAX-UGFSB_nc_htscontent-cph2-1?jpeg&quot;)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Artlist</div> <div class="story-count-con"> <div class="story-brand-number">4</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player:vimeo;com/external/661072039:sd;mp4?s=2de96ddc6ca1d36541f4076ff14fd508c38fa61c&amp;profile_id=165#t=12.8" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <!-- <input type="hidden" class="jetboost-list-item" value="156-artlist" /> --></div> </div> </div>

如您所見,我只向父列表添加了兩個事件:在mousemovemouseout上(它們都冒泡,而不是mouseentermouseleave ,它們不會冒泡)。

如果我們當前懸停一個視頻並且它沒有播放,我們正在播放它。 mouseout中,我們選擇了所有未懸停的<video>元素,如果我們發現任何正在播放的元素,我們將停止它。

我相信這就是你想要的,對吧?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM