IntersectionObserver 上执行observe 失败的原因是什么?
What causes this failure to execute observe on IntersectionObserver?
我正在 Intersection Observer API 的帮助下制作纯粹的 JavaScript 无限滚动 API。
可滚动项目是 posts 来自 jsonplaceholder.typicode.com API.
我最初加载 5 个帖子,然后每次滚动到底部时再加载 5 个。
class InfiniteScroll {
constructor() {
this.postsContainer = document.querySelector('#postsContainer');
this.visiblePosts = [];
this.postsLot = [];
this.observer = null;
this.hasNextPage = true;
this.postsUrl = 'https://jsonplaceholder.typicode.com/posts';
this.limit = 5;
this.iterationCount = 0;
}
loadPosts() {
fetch(this.postsUrl)
.then(res => res.json())
.then(posts => {
this.postsLot = posts.slice(this.iterationCount * this.limit, this.limit);
// Add items to the array of visible posts
// with every iteration
if(this.postsLot.length > 0) {
this.postsLot.map(entry => {
return this.visiblePosts.push(entry);
});
}
this.renderVisiblePosts();
})
.catch(err => console.log(err));
}
renderVisiblePosts() {
let output = '';
this.visiblePosts.forEach(post => {
output += `<div class="post">
<h2>${post.id} ${post.title}</h2>
<p>${post.body}</p>
</div>`;
});
this.postsContainer.innerHTML = output;
}
getLastPost() {
return this.visiblePosts[this.visiblePosts.length - 1];
}
iterationCounter() {
if (this.hasNextPage) {
this.iterationCount = this.iterationCount + 1;
}
}
bindLoadMoreObserver() {
if (this.postsContainer) {
this.observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry && entry.isIntersecting) {
console.log('bottom');
observer.unobserve(entry.target);
this.loadPosts();
this.iterationCounter();
if (this.hasNextPage) {
observer.observe(this.getLastPost());
}
}
});
});
this.observer.observe(this.getLastPost());
}
}
init() {
this.getLastPost();
this.loadPosts();
this.bindLoadMoreObserver();
}
}
const infiniteScroll = new InfiniteScroll();
infiniteScroll.init();
body, body * {
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
.post {
margin: 20px;
padding: 15px;
border: 1px solid #ccc;
border-radius: 5px;
}
p {
line-height: 1.5;
}
<div id="postsContainer"></div>
问题
浏览器不会观察最后一个元素何时进入视图,而是抛出错误:
Uncaught TypeError: Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'.
您没有按照当前的实施方式观察 Element
。您正在观察 visiblePosts
数组中的最后一个不是元素的对象。
您可以使用 this.postsContainer.lastElementChild
获取最后一个元素,前提是在那之前 this.postsContainer
有子元素。
我正在 Intersection Observer API 的帮助下制作纯粹的 JavaScript 无限滚动 API。
可滚动项目是 posts 来自 jsonplaceholder.typicode.com API.
我最初加载 5 个帖子,然后每次滚动到底部时再加载 5 个。
class InfiniteScroll {
constructor() {
this.postsContainer = document.querySelector('#postsContainer');
this.visiblePosts = [];
this.postsLot = [];
this.observer = null;
this.hasNextPage = true;
this.postsUrl = 'https://jsonplaceholder.typicode.com/posts';
this.limit = 5;
this.iterationCount = 0;
}
loadPosts() {
fetch(this.postsUrl)
.then(res => res.json())
.then(posts => {
this.postsLot = posts.slice(this.iterationCount * this.limit, this.limit);
// Add items to the array of visible posts
// with every iteration
if(this.postsLot.length > 0) {
this.postsLot.map(entry => {
return this.visiblePosts.push(entry);
});
}
this.renderVisiblePosts();
})
.catch(err => console.log(err));
}
renderVisiblePosts() {
let output = '';
this.visiblePosts.forEach(post => {
output += `<div class="post">
<h2>${post.id} ${post.title}</h2>
<p>${post.body}</p>
</div>`;
});
this.postsContainer.innerHTML = output;
}
getLastPost() {
return this.visiblePosts[this.visiblePosts.length - 1];
}
iterationCounter() {
if (this.hasNextPage) {
this.iterationCount = this.iterationCount + 1;
}
}
bindLoadMoreObserver() {
if (this.postsContainer) {
this.observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry && entry.isIntersecting) {
console.log('bottom');
observer.unobserve(entry.target);
this.loadPosts();
this.iterationCounter();
if (this.hasNextPage) {
observer.observe(this.getLastPost());
}
}
});
});
this.observer.observe(this.getLastPost());
}
}
init() {
this.getLastPost();
this.loadPosts();
this.bindLoadMoreObserver();
}
}
const infiniteScroll = new InfiniteScroll();
infiniteScroll.init();
body, body * {
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
.post {
margin: 20px;
padding: 15px;
border: 1px solid #ccc;
border-radius: 5px;
}
p {
line-height: 1.5;
}
<div id="postsContainer"></div>
问题
浏览器不会观察最后一个元素何时进入视图,而是抛出错误:
Uncaught TypeError: Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'.
您没有按照当前的实施方式观察 Element
。您正在观察 visiblePosts
数组中的最后一个不是元素的对象。
您可以使用 this.postsContainer.lastElementChild
获取最后一个元素,前提是在那之前 this.postsContainer
有子元素。