表格由三部分组成,表格头部,表格体,表格的分页栏。本文实现的分页表格,适合后端返回所有数据后,采用前端分页。数据如果有更新,需要手动调用更新方法
表格和分页的html部分
<div id="tableContainer" style="overflow: scroll; width: 100%;">
<table id="'table" width="1000px" class="tableClass">
<thead id="thead"></thead>
<tbody id="tbody"></tbody>
</table>
</div>
<div class="pagination-nav">
<ul class="pagination" id="pagination"></ul>
</div>
css样式部分
ul {
list-style: none;
margin: 0px;
padding: 0px;
}
body {
margin: 0;
}
.tableClass {
min-width: 400px;
border: 1px solid red;
overflow-x: scroll;
}
.tableClass {
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
margin-left: 2px;
margin-right: 2px;
}
.tableClass td, .tableClass th {
border: 1px solid #ddd;
padding: 2px;
min-width: 60px;
}
.tableClass tr {background-color: #f2f2f2;}
/* .tableClass tr:nth-child(odd){background-color: #f2f2f2;} */
.tableClass tr:nth-child(5n){background-color: #dfebdb;}
.tableClass tr:hover {background-color: #ddd;}
.tableClass th {
/* padding-top: 12px;
padding-bottom: 12px; */
text-align: left;
background-color: #4CAF50;
color: white;
}
#tableContainer ::-webkit-scrollbar {
width: 8px;
height: 8px;
}
#tableContainer ::-webkit-scrollbar-thumb {
background-color: rgba(71, 71, 71, 0.63);
border-radius: 4px;
}
.pagination-nav {
margin-top: 5px;
margin-bottom: 5px;
border-radius: 6px;
padding: 0;
display: flex;
}
.pagination {
display: -ms-flexbox;
display: flex;
padding-left: 2px;
list-style: none;
border-radius: 0.25rem;
}
#pageCurrentInfo {
line-height: 30px;
font-size: 16px;
color: wheat;
}
.active {
background-color: #007bff!important;
color: white!important;
}
.page-link {
position: relative;
display: block;
padding: 0.25rem 0.75rem;
margin-left: -1px;
line-height: 1.25;
text-decoration:none;
color: #007bff;
background-color: #fff;
border: 1px solid #dee2e6;
}
.page-item:first-child .page-link {
margin-left: 0;
border-top-left-radius: 0.25rem;
border-bottom-left-radius: 0.25rem;
}
.page-item:last-child .page-link {
margin-left: 0;
border-top-right-radius: 0.25rem;
border-bottom-right-radius: 0.25rem;
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
background-color: rgba(71, 71, 71, 0.63);
border-radius: 4px;
}
js部分
分页逻辑是,>1页,展示分页,5页以内,展示5个页码,超出5页,展示“向前”,“向后”,以及包括点击页的相邻5页的页码。
var paginationUl = document.getElementById('pagination');
var tableHead = document.getElementById('thead')
var tableBody = document.getElementById('tbody')
paginationUl.addEventListener('click', event => {
let page = event.target.dataset.page;
if(page === 'prev') {
tableObj.curPage > 1 ? tableObj.updateTableRowsByPageNum(tableObj.curPage-1, true) : null;
}else if(page === 'next') {
tableObj.curPage < tableObj.total ? tableObj.updateTableRowsByPageNum(tableObj.curPage+1, true) : null;
}else {
clearLiActive();
event.target.classList.add('active');
tableObj.updateTableRowsByPageNum(parseInt(event.target.dataset.page), false)
}
})
// 清除li的active
function clearLiActive() {
let activeli =Array.from(paginationUl.childNodes).filter(node => node.firstChild.className.includes('active'));
activeli.length > 0 ? activeli[0].firstChild.classList.remove('active') : null;
}
function createPagination(pageNum, activePage = 1) {
let str = ''
if(pageNum <= 5) {
for(let i = 1; i <= pageNum; i++) {
let className = i===activePage ? "page-link active" : "page-link"
str += '<li class="page-item">' + '<a class="'+ `${className}` +'" href="#" data-page=' + i + ' >' + i + '</a></li>'
}
}else {
str += '<li class="page-item">' + '<a class="page-link" href="#" data-page=' + 'prev' + ' >' + '<' + '</a></li>'
for(let i = Math.min(activePage, pageNum-4); i < Math.min(5 + activePage, pageNum+1); i++) {
let className = i===activePage ? "page-link active" : "page-link"
str += '<li class="page-item">' + '<a class="' + className +'" href="#" data-page=' + i + ' >' + i + '</a></li>'
}
str += '<li class="page-item">' + '<a class="page-link" href="#" data-page=' + 'next' + ' >' + '>' + '</a></li>'
}
paginationUl.innerHTML = str;
}
class MyTable {
constructor(columns, pageSize, data) {
this.columns = columns;
this.pageSize = pageSize;
this.curPage = 1;
this.total = 1; // 总页数
this.data = data;
this.tableHeadDom = null;
this.tableBodyDom = null;
}
init(headDom, bodyDom) {
this.tableHeadDom = headDom;
this.tableBodyDom = bodyDom;
this.iniTableHeader(this.tableHeadDom);
this.updateTableRowsByPageNum(this.curPage);
}
iniTableHeader(target) {
let str = '<tr>'
for(let item of this.columns) {
str += '<th>' + item.title + '</th>'
}
target.innerHTML = str + '</tr>'
}
createTableRowsToTarget(target, data) {
let arr = []
for(let i = 0, size = data.length; i < size; i++) {
let str = '<tr>';
for(let item of this.columns) {
str += '<td>' + data[i][item.field] + '</td>'
}
arr.push(str.concat('</tr>'))
}
target.innerHTML = arr.join('')
}
//更新第pageNo页数据,第二个参数代表更新分页
updateTableRowsByPageNum(pageNo, updatePagination = true) {
console.log(pageNo, this.data, this.pageSize, updatePagination)
this.curPage = pageNo;
let pageNum = Math.ceil(this.data.length/this.pageSize);
if(pageNum !== this.total) {
this.total = pageNum;
}
if(pageNum >= 2) {
updatePagination && createPagination(pageNum, pageNo)
}
this.createTableRowsToTarget(this.tableBodyDom, this.data.slice((pageNo - 1) * this.pageSize, pageNo * this.pageSize))
}
}
使用MyTable类
// 表格的列,field为字段名,title为展示的表头
var tableColumns = [
{
field: 'id',
title: 'ID'
},
{
field: 'KeyFactor1',
title: '因素1'
},
{
field: 'KeyFactor2',
title: '因素2'
},
{
field: 'KeyFactor3',
title: '因素3'
},
{
field: 'KeyFactor4',
title: '因素4'
},
{
field: 'KeyFactor5',
title: '因素5'
},
]
var data = mockTableData(tableColumns.map(item => item.field), 20)
var tableObj = new MyTable(tableColumns, 3, data)
tableObj.init(tableHead, tableBody)
// 构造模拟数据,columns为数组,如['a', 'b', 'c']
function mockTableData(columns, size = 50) {
let arr = [];
for(let i = 0; i < size; i++) {
let row = columns.reduce((prev, cur) => {
prev[cur] = Math.random().toFixed(3);
return prev;
}, {});
arr.push(row);
}
return arr;
}
如果data有更新,可以手动调用 tableObj.updateTableRowsByPageNum(1);//更新第一页数据
后续改进点,加入支持后端分页,点击页数,请求数据。