延迟加载的路口观察器

Intersection Observer with lazy loading

我想通过此示例使用图像实现此行为 https://codepen.io/ryanfinni/pen/jONBEdX。 唯一的区别是,在切换 img 可见性时,对于它可见的每个 div,我想调用一个端点来检索数据并通过发送相应的数据来填充 html -id 作为参数。

到目前为止,我所拥有的仅适用于第一项。我怎样才能让它适用于我拥有的所有项目并通过数据 ID 定位它们,类似于 data.src

的示例
function handleIntersection(entries) {
  entries.map((entry) => {
    if (entry.isIntersecting) {
      entry.target.src = entry.target.dataset.src;
      entry.target.classList.add('loaded')
      observer.unobserve(entry.target);
    }
  });
}

这是我的代码

const LIST = document.querySelector('.city-list');
async function getData() {
  try {
    let response = await fetch('https://raw.githubusercontent.com/ashes27/infinite/master/ids.json');
    if (response.status == 200) {
      let data = await response.json();
      return data;
    } else {
      throw new Error(response.status);
    }
  } catch (error) {
    console.log(error);
  }
}

getData().then((data) => {
  for (const details in data.data.items) {
    const LI = document.createElement('li');
    const TITLE = document.createElement('h2');
    TITLE.className = 'city-title';
    TITLE.innerText = data.data.items[details].title;
    LI.appendChild(TITLE);
    LIST.appendChild(LI);
    for (const id in data.data.items[details].ids) {
      const DIV = document.createElement('div');
      DIV.setAttribute('data-id', data.data.items[details].ids[id]);
      DIV.className = 'wrapper';
      const markup = `
       <div class="city-wrapper" >
          <div class="result-wrapper">
            <div class="image-wrapper">
              <img src=""/>
            </div>
            <div class="content-wrapper">
              <div class="content-info">
                <div class="info-wrapper">
                  <h2></h2>
                  <span class="address"></span>
                </div>
              </div>
              <p class="description"></p>
              </div>
            </div>
          </div>
        </div>
      `;
      DIV.innerHTML = markup;
      LI.appendChild(DIV);
    }
  }
});

var observer = new IntersectionObserver(
  function (entries) {
    if (entries[0].isIntersecting === true) {
      observer.unobserve(document.querySelector('.city-list'));
      const getInfo = async function (post) {
        let infoResponse = await fetch('https://raw.githubusercontent.com/ashes27/infinite/master/single-item.json');
        let info = await infoResponse.json();
        return info;
      };
      getInfo().then((info) => {
        console.log(info);
        let itemsInfo = info.data.items;
        const DIV = LIST.querySelector('.wrapper');
        console.log(DIV);
        const markup = `
        <div class="city-wrapper" >
          <div class="result-wrapper">
            <div class="image-wrapper">
              <img src="${itemsInfo.mainImgUrl}"/>
            </div>
            <div class="content-wrapper">
              <div class="content-info">
                <div class="info-wrapper">
                  <h2>${itemsInfo.visitTitle}</h2>
                  <span class="address">${itemsInfo.address}</span>
                </div>
              </div>
              <p class="description">${itemsInfo.mainDescription}</p>
              </div>
            </div>
          </div>
        </div>
        `;
        DIV.innerHTML = markup;
      });
    }
  },
  { threshold: [0] }
);

observer.observe(document.querySelector('.city-list'));
.city-wrapper {
  height: 440px;
}

img {
  width: 400px;
}
 <div style="height: 400px;"></div>
  <div style="height: 400px;"></div>
  <div style="height: 400px;"></div>
  <div style="height: 400px;"></div>
  <div style="height: 400px;"></div>
  <div style="height: 400px;"></div>
  <div style="height: 400px;"></div>
  <div style="height: 400px;"></div>

  <ul class="city-list">
  </ul>

提前致谢!

您已让 observer 观察 .city-list 与视口的交叉点。但是您想知道列表中的任何 .wrapper 元素(带有 data-id 的元素)何时可见(或即将可见)。

因此您必须 .observe() 这些 div.wrapper 元素而不是完整列表:

observer.observe(DIV);

要删除刚刚变为可见的元素,您必须使用当前 IntersectionObserverEntry:

target 属性
observer.unobserve(entries[0].target);

您正在寻找的 data-id 也可以通过相同的方式获得 属性:

const dataId = entries[0].target.dataset.id;

因为我们要“观察”多个元素,所以我们必须相应地调整逻辑:

entries.forEach(entry => {
  // ...
});

一个完整但略有减少的(虚拟数据,没有getInfo())示例:

const observer = new IntersectionObserver(
  function (entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting === true) {
        observer.unobserve(entry.target); // remove the current item from the "watchlist"
        console.log(entry.target.dataset.id); // the id you're looking for
      }
    });
  },
  { threshold: [0] }
);

async function getData() {
  // dummy data
  return Promise.resolve({
    data: {
      items: {
        city1: { title: "City 1", ids: [1, 2, 3] },
        city2: { title: "City 2", ids: [4, 5, 6] }
      }
    }
  })
};

getData().then((data) => {
  const LIST = document.querySelector('.city-list');
  
  for (const details in data.data.items) {
    const LI = document.createElement('li');
    
    const TITLE = document.createElement('h2');
    TITLE.className = 'city-title';
    TITLE.innerText = data.data.items[details].title;
    LI.appendChild(TITLE);
    
    LIST.appendChild(LI);
    
    for (const id in data.data.items[details].ids) {
      const DIV = document.createElement('div');
      DIV.setAttribute('data-id', data.data.items[details].ids[id]);
      DIV.className = 'wrapper';
      
      const markup = `<div class="city-wrapper" >...</div>`;
      
      DIV.innerHTML = data.data.items[details].ids[id] + "<br />" /* so the ID is directly visible */ + markup;
      LI.appendChild(DIV);
      
      observer.observe(DIV); // add the current DIV to the "watchlist"
    }
  }
});
.city-wrapper { height: 440px; }
img { width: 400px; }
<ul class="city-list"></ul>

或此处:https://jsfiddle.net/sDSJrPqw/L0wd6kja/5/