延迟加载的路口观察器
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://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>