js之页面列表加载常用方法总结

导语:最近由于一些事情需要处理,所以没来得及写技术总结了。今天终于可以坐下来好好的梳理一下脉络,说一下那个在日常前端开发过程中,常用到的页面列表加载的方法总结。这里介绍三种方法,分别是分页加载、按钮加载以及滚动加载。

目录

  • 方法简介
  • 代码实现
  • 效果预览

方法简介

在日常的前端开发过程中,我们经常会碰到列表很长,不可能完全显示出来,所以就要进行分页,每页固定显示几条,然后下面是页数,点到哪页显示哪页的内容。

除了常见的分页加载外,还要点击按钮加载,这种加载方法就是不需要点击下一页这种了,直接点击按钮往第一页的后面补上下一页的内容,非常方便。

除了以上两种,滚动加载也是用的比较多的一种列表加载方法,下面就这三种方法做一下总结归纳,方便需要的小伙伴们使用。

封装实现

下面就对三种方法分别做一下原理解析和方法实现。

下面的列表使用了JSONPlaceholder站点上的一些数据作为列表来源。

分页加载

当页面的需求是要显示一个列表或者表格,总数很多放不下,这时候可以把全部的数据分成多页,每页显示固定的条数,计算出总页数,然后渲染一下就可以了。

  • 页面布局
<div class="wrap">
    <ul id="list"></ul>
    <ul id="pages"></ul>
</div>
.wrap {
    max-width: 960px;
    margin: 0 auto;
    padding: 15px 0;
}

.wrap li {
    padding: 5px 0;
    list-style: square;
}

.wrap li h3,
.wrap li p {
    text-transform: capitalize;
}

.wrap li h3:hover {
    color: #f00;
    cursor: pointer;
}

#pages li {
    display: inline-block;
    margin-right: 10px;
    list-style: none;
}

#pages button {
    width: auto;
    min-width: 40px;
    height: 40px;
    background: #fff;
    box-shadow: 0 0 5px #fff;
    border: 1px solid #ccc;
    border-radius: 5px;
    font-size: 16px;
}

#pages button:hover,
#pages button.active {
    color: #fff;
    border-color: #f00;
    background: #f00;
    cursor: pointer;
}

#pages button.dis {
    cursor: no-drop;
}

.wrap .loading {
    line-height: 70vh;
    text-align: center;
    list-style: none;
}

.wrap .nodata {
    list-style: none;
    text-align: center;
}
  • 定义变量
let datas = [], // 分组列表
current = 1, // 当前页
pages = 0, // 总页数
total = 0, // 总数
listElem = document.getElementById('list'), // 列表内容
pageElem = document.getElementById('pages'); // 页数按钮
  • 处理数据

我们使用axios来获取json数据,模拟抓取接口的情况。

// 获取列表
async function getList (page = 1) {
    let res = await axios.get('https://jsonplaceholder.typicode.com/posts');
    if (res.status === 200) {
        let data = sliceData(res.data);
        pages = data.pages;
        total = res.data.length;
        datas = [...data.list];
        return {
            code: 200,
            msg: 'get_succ',
            data: {
                list: data.list[page-1],
                current: page,
                pages: data.pages,
                total: list.length,
            }
        }
    }
}

写一个切割数组的方法,分成等份的数组。

// 处理数据
function sliceData (list) {  
    let newArr = [],step = 10,pages = Math.ceil(list.length/10);
    for (let i = 0; i < list.length; i+=step) {
        let item = list.slice(i, i+step);
        newArr.push(item);
    }
    return {
        list: newArr,
        pages,
    };
}
  • 显示列表
showList(current);

// 显示列表
async function showList (current) {
    let data = null;
    listElem.innerHTML = '';
    listElem.innerHTML = '<li class="loading">加载中...</li>';
    if (datas && datas.length) {
        data = {
            code: 200,
            msg: 'get_succ',
            data: {
                list: datas[current-1],
                current: current,
                pages,
                total,
            }
        }
    } else {
        data = await getList(current);
    }
    if (data.code === 200) {
        let list = data.data.list;
        if (list && list.length) {
            let liStr = '',pageStr = '';
            for (const item of list) {
                liStr += `<li>
                    <h3>${item.title}</h3>
                    <p>${item.body}</p>
                </li>`;
            }
            
            setTimeout(() => {
                listElem.innerHTML = liStr;
            }, 1000);

            if (pageElem.innerText === '') {
                for (let i = 0; i < data.data.pages; i++) {
                    pageStr += `<li><button class="page" data-id="${i+1}">${i+1}</button></li>`
                }
                pageElem.innerHTML = `
                <li><button id="start" data-id="1">首页</button></li>
                <li><button id="prev">上一页</button></li>
                ${pageStr}
                <li><button id="next">下一页</button></li>
                <li><button id="end" data-id="${data.data.pages}">尾页</button></li>`;
                showHighLight(current);
                addClick();
            }
        } else {
            listElem.innerHTML = '<li class="nodata">暂无数据</li>';
        }
    }
}
  • 添加点击事件
// 添加点击
function addClick () {  
    let btns = document.querySelectorAll('#pages li button');
    for (const item of btns) {
        item.addEventListener('click', toggleList, false);
    }
}
  • 切换页面内容
// 切换页面
function toggleList (event) {  
    let id = event.target.dataset.id,
    bid = event.target.id;
    if (id) {
        current = Number(id);
    }
    if (bid == 'prev') {
        if (current <= 1) {
            current = 1;
        } else {
            current--;
        }
    } else if (bid == 'next') {
        if (current >= pages) {
            current = pages;
        } else {
            current++;
        }
    }
    showHighLight(current, bid);
    showList(current);
}
  • 显示高亮
// 显示高亮
function showHighLight (current, bid) {
    let btns = document.querySelectorAll('.page'),
    startBtn = document.getElementById('start'),
    endBtn = document.getElementById('end');
    for (const item of btns) {
        item.className = 'page';
    }
    btns[current-1].className = 'page active';
    startBtn.className = current == 1 ? 'active dis' : '';
    endBtn.className = current == pages ? 'active dis' : '';
}

其中渲染好页面后,还加了一个定时器是模拟从服务器获取数据等待过程的效果,真实情况下不需要这样。

按钮加载

按钮加载的方法和上面的相似,也就是分页那块改成一个按钮了,不断在现有的列表中添加新的列表内容,其余和分页加载没有太大区别。

  • 页面结构
<div class="wrap">
    <ul id="list"></ul>
    <p class="loadmore">加载中...</p>
    <p class="more-box">
        <button id="more">加载更多</button>
    </p>
</div>
  • 页面美化
.more-box {
    text-align: center;
}

#more {
    padding: 10px;
    background: none;
    border: 1px solid #ccc;
    border-radius: 5px;
}

#more:hover {
    cursor: pointer;
    border-color: #f00;
    background-color: #f00;
    color: #fff;
}

.loadmore {
    text-align: center;
}

.hide {
    display: none;
}
  • 获取变量
let loadMore = document.querySelector('.loadmore'),
moreBtn = document.getElementById('more');
  • 点击加载更多
// 添加点击
moreBtn.addEventListener('click', addList, false);

// 切换页面
function addList () {
    if (current < pages) {
        current+=1;
        showList(current);
    } else {
        moreBtn.innerText = '没有更多了';
    }
}
  • 显示页面

在原有的显示列表方法基础上修改几处就好了。

// 显示列表
async function showList (current) {
    let data = null;
    loadMore.className = 'loadmore';
    if (datas && datas.length) {
        data = {
            code: 200,
            msg: 'get_succ',
            data: {
                list: datas[current-1],
                current: current,
                pages,
                total,
            }
        }
    } else {
        data = await getList(current);
    }
    if (data.code === 200) {
        let list = data.data.list;
        if (list && list.length) {
            let liStr = '',pageStr = '';
            for (const item of list) {
                liStr += `<li>
                    <h3>${item.title}</h3>
                    <p>${item.body}</p>
                </li>`;
            }

            listElem.innerHTML += liStr;

        } else {

            listElem.innerHTML = '<li class="nodata">暂无数据<li>';
        }

        
        setTimeout(() => {
            loadMore.className = 'loadmore hide';
        }, 1000);
    }
}

滚动加载

滚动加载就是在页面滚动到底部后自动添加新的一页内容到当前列表后面,每次滚动根据计算动态添加内容。

就是在按钮加载的基础上更改而来的,具体的原理是当文档的到顶部的高度加上文档的可视化高度大于文档的滚动高度的时候就加载页面。

  • 页面结构
<div class="wrap">
    <ul id="list"></ul>
    <p class="loadmore">加载中...</p>
</div>
  • 滚动判断
document.addEventListener('scroll', checkScroll, false);
function checkScroll () {  
    let scrollTop = document.documentElement.scrollTop,
    clientHei = document.documentElement.clientHeight,
    scrollHeight = document.documentElement.scrollHeight;
    if (scrollTop + clientHei >= scrollHeight) {
        addList();
    }
}

// 切换页面
function addList () {
    if (current < pages) {
        current+=1;
        showList(current);
    } else {
        loadMore.innerText = '没有更多了';
    }
}

效果预览

  • 分页加载

在这里插入图片描述

在线预览

  • 按钮加载
    在这里插入图片描述

在线预览

  • 滚动加载

在这里插入图片描述
在线预览

最后的话

以上就是我在日常开发过程中的用的几种加载的方法,如果有什么问题,欢迎邮箱联系我。

posted @ 2022-09-17 18:32  MarkGuan  阅读(758)  评论(0编辑  收藏  举报