实现效果
预览
准备工作
数据
使用了jsonplaceholder的数据。点击此处查看测试数据。
我们可以添加参数:_limit(表示每页几条数据)和_page(表示第几页):
https://jsonplaceholder.typicode.com/posts?_limit=5&_page=2
HTML与CSS
我们需要一个列表容器:
<div class="posts-container" id="posts-container"></div>
|
一个loader动画:
<div class="loader"> <div class="circle"></div> <div class="circle"></div> <div class="circle"></div> </div>
|
完整HTML和CSS请查看Github源代码。
fetch API
jsonplaceholder推荐的获取方式是使用fetch:
fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) .then(json => console.log(json))
|
fetch方法传入一个url作为参数,返回一个Promise对象。
fetch请求成功之后,得到的是一个Response对象。response.json()也是一个异步操作,取出所有内容,转化为JSON对象。获取到数据之后,我们便可以渲染到页面了。
实现
要实现无限滚动的效果,我们需要监听window的scroll事件,滚动触底的时候再触发请求数据的操作。
请求数据
由于我们之后在滚动触底的时候还需要渲染数据,所以将请求封装一下:
let limit = 5; let page = 1;
function fetchData() { return fetch(`${url}/posts?_limit=${limit}&_page=${page}`).then((response) => response.json() ); }
function showData() { fetchData().then((data) => { render(data); }); }
|
渲染数据
将获取到的数据(数组形式)渲染到页面:
function render(data) { data.forEach((post) => { const postEl = document.createElement("div"); postEl.classList.add("post"); postEl.innerHTML = `<div class="number">${post.id}</div> <div class="post-info"> <div class="post-title">${post.title}</div> <p class="post-body">${post.body}</p> </div>`; postsContainer.appendChild(postEl); }); }
|
判断滚动触底
window.addEventListener("scroll", () => { const { scrollTop, scrollHeight, clientHeight } = document.documentElement; if (scrollTop + clientHeight >= scrollHeight - 10) { page++; showData(); } });
|
这里会出现滚动触底之后会请求多次的情况,这个问题需要用到函数节流技术解决。
使用async / await 简化
在使用到Promise的地方,可以用async / await 改写,简化代码。
async function fetchData() { let res = await fetch(`${url}/posts?_limit=${limit}&_page=${page}`); return await res.json(); }
async function showData() { let data = await fetchData(); render(data); }
|
函数节流
函数节流,指定时间间隔内只会执行一次任务。
本项目中,滚动触底时会多次触发scroll事件,因此会发送多次请求。函数节流技术可以解决这个问题:
function load() { page++; showData(); }
function throttle(fn, delay) { let canUse = true; return function () { if (canUse) { fn.apply(this, arguments); canUse = false; setTimeout(() => (canUse = true), delay); } }; } const throttled = throttle(load, 1000);
|
完整代码
完整代码请查看Github。
参考
Check if a user has scrolled to the bottom