Kỹ thuật phân trang sử dụng components
Create by: Hữu Định - Minh Đức
Nội dung chính
1. Mô tả ứng dụng
1. Mô tả ứng dụng
Input: Ta có 1 danh sánh khách hàng lưu trữ trong 1 file json
Process:
2. Thuật toán
1. Thuật toán
Ý tưởng phân trang:
Chia dữ liệu thành các phần bằng nhau và chỉ hiện thị 1 phần dữ liệu được chia
Page hiện tại currRange = pageNum * paginationLimit;
Trước 1 page prevRange = (pageNum - 1) * paginationLimit;
data.forEach((item, index) => {
if (index >= prevRange && index < currRange) {
newData.push(item)
}
});
3. Code
3. Code PageSplit
3.1 Cấu trúc thư mục / Tạo file: index.html
Yêu cầu:
Tạo file: index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Split</title>
<link rel="stylesheet" href="https://huudinh.github.io/assets/sass/lib.min.css">
<link rel="stylesheet" href="./assets/sass/pagesplit.min.css">
</head>
<body>
<div id="root"></div>
<script src="src/index.js" type="module"></script>
</body>
</html>
3. Code PageSplit
3.2 Cấu trúc thư mục / Tạo file: assets/sass/pagesplit.scss
.dataTable{
margin:10px;
&__title{
background:#ededed;
font-weight: 600;
padding:5px 0;
margin:0 0 10px;
border-bottom: 1px solid #ccc;
}
&__content{
margin-right:15px;
margin-left:15px;
.row:nth-child(even){
background:#eee;
}
}
.col{
padding:5px 10px;
}
a{
color:blue;
}
}
.pagination{
display: flex;
justify-content: center;
ul{
padding:0;
}
li{
list-style:none;
cursor: pointer;
box-shadow: 0px 2px 8px rgb(0 0 0 / 10%);
&:nth-child(1){
border-left:1px solid #ccc;
}
}
&__item{
padding:5px 12px;
border-right:1px solid #ccc;
border-bottom:1px solid #ccc;
border-top:1px solid #ccc;
&.active, &:hover{
background:#0d6efd;
color:#fff;
}
}
.d-none{
display: none;
}
}
3. Code PageSplit
3.3 Cấu trúc thư mục / Tạo file: index.js
import Lead from "./components/Lead.js"
const lead = new Lead();
document.getElementById('root').appendChild(lead.render())
3. Code PageSplit
3.4 Cấu trúc thư mục / Tạo file: src/apis/leadList.json
[{
"name": "Nguyễn Văn A",
"phonenumber": "01234567890",
"nameFb": "Đức Đoàn",
"linkFb": "https://www.facebook.com/",
"service": "Nâng mũi",
"branch": "Kangnam Sài Gòn",
"script": "Kịch bản nâng mũi",
"interactive": "https://d1hjkbq40fs2x4.cloudfront.net/2017-12-12/files/eos-6d-mark-ii-sample-image_1723.jpg",
"note": "Không có gì",
"createAt": "2022-12-15"
}, {
"name": "Nguyễn Văn A",
"phonenumber": "01234567891",
"nameFb": "Đức Đoàn",
"linkFb": "https://www.facebook.com/",
"service": "Nâng mũi",
"branch": "Kangnam Hà Nội",
"script": "Kịch bản nâng mũi",
"interactive": "https://d1hjkbq40fs2x4.cloudfront.net/2017-12-12/files/eos-6d-mark-ii-sample-image_1723.jpg",
"note": "Không có gì",
"createAt": "2022-12-16"
}]
3. Code PageSplit
3.5 Cấu trúc thư mục / Tạo file: src/index.js
import Lead from "./components/Lead.js"
const lead = new Lead();
document.getElementById('root').appendChild(lead.render())
3. Code PageSplit
3.6 Cấu trúc thư mục / Tạo file: src/components/Lead.js
import { getLead } from "../apis/lead.js"
import LeadList from "./LeadList.js";
import Pagination from "./Pagination.js";
class Lead {
index = 1
constructor() {
this.$dataTable = document.createElement('div')
this.$dataTable.className = `dataTable`;
this.$table = document.createElement('div')
this.$pagiBox = document.createElement('div')
this.$pagiBox.className = `dataTable__page`
this.getAllLead()
}
setIndex = (index) => {
this.index = index
}
3. Code PageSplit
3.6 Cấu trúc thư mục / Tạo file: src/components/Lead.js
getAllLead = async () => {
try {
const res = await getLead({
pageNum: this.index,
})
this.$leadList = new LeadList({ data: res.render })
this.$pagination = new Pagination({
count: res.pageCount, index: this.index, setIndex: this.setIndex, getAllData: this.getAllLead })
if (res.pageCount === 0) {
this.$table.className = 'text-center';
this.$table.innerHTML = 'Không có dữ liệu';
this.$pagiBox.innerHTML = ''
return
}
this.$table.innerHTML = ''
this.$table.className = 'dataTable__list';
this.$table.appendChild(this.$leadList.render());
this.$pagiBox.innerHTML = ''
this.$pagiBox.appendChild(this.$pagination.render());
} catch (e) {
console.log(e);
return
}
}
3. Code PageSplit
3.6 Cấu trúc thư mục / Tạo file: src/components/Lead.js
render() {
this.$dataTable.appendChild(this.$table);
this.$dataTable.appendChild(this.$pagiBox);
return this.$dataTable;
}
}
export default Lead
3. Code PageSplit
3.7 Cấu trúc thư mục / Tạo file: src/apis/lead.js
const URL = 'src/apis/leadList.json'
export const getLead = async({ pageNum }) => {
try {
const newData = []
// Call API
const response = await fetch(URL);
const data = await response.json();
// Pagination
const paginationLimit = 15
const pageCount = Math.ceil(data.length / paginationLimit);
const prevRange = (pageNum - 1) * paginationLimit;
const currRange = pageNum * paginationLimit;
// getData
data.forEach((item, index) => {
if (index >= prevRange && index < currRange) {
newData.push(item)
}
});
return {
render: newData,
pageCount: pageCount
}
} catch (e) {
console.log(e);
return
}
}
3. Code PageSplit
3.8 Cấu trúc thư mục / Tạo file: src/components/LeadItem.js
class LeadItem {
constructor({ name, phonenumber, nameFb, linkFb, service, branch, script, interactive, note }) {
this.data = {
name: name,
phonenumber: phonenumber,
nameFb: nameFb,
linkFb: linkFb,
service: service,
branch: branch,
script: script,
interactive: interactive,
note: note,
}
this.$tr = document.createElement('div')
this.$tr.className = 'row'
this.$name = new Cell(name);
this.$phonenumber = new Cell(phonenumber);
this.$linkFb = new CellLink(nameFb, linkFb);
this.$service = new Cell(service);
this.$branch = new Cell(branch);
this.$script = new Cell(script);
this.$interactive = new CellLink('Link ảnh', interactive);
this.$note = new Cell(note);
}
3. Code PageSplit
3.8 Cấu trúc thư mục / Tạo file: src/components/LeadItem.js
render() {
this.$tr.appendChild(this.$name.render());
this.$tr.appendChild(this.$phonenumber.render());
this.$tr.appendChild(this.$linkFb.render());
this.$tr.appendChild(this.$service.render());
this.$tr.appendChild(this.$branch.render());
this.$tr.appendChild(this.$script.render());
this.$tr.appendChild(this.$interactive.render());
this.$tr.appendChild(this.$note.render());
return this.$tr
}
}
class Cell {
constructor(name) {
this.$container = document.createElement('div');
this.$container.className = 'col';
this.$container.innerHTML = name;
}
render () {
return this.$container;
}
}
3. Code PageSplit
3.8 Cấu trúc thư mục / Tạo file: src/components/LeadItem.js
class CellLink {
constructor(name, link) {
this.$container = document.createElement('div');
this.$container.className = 'col';
this.$linkText = document.createElement('a');
this.$linkText.target = '_blank';
this.$linkText.href = link;
this.$linkText.innerHTML = name;
}
render () {
this.$container.appendChild(this.$linkText);
return this.$container;
}
}
export { Cell, LeadItem };
3. Code PageSplit
3.9 Cấu trúc thư mục / Tạo file: src/components/LeadList.js
import {LeadItem, Cell} from "./LeadItem.js"
class LeadList {
constructor({ data }) {
this.data = data
this.$container = document.createElement('div')
this.$theadTr = document.createElement('div')
this.$theadTr.className = 'row dataTable__title'
this.$name = new Cell('Họ và tên');
this.$phoneNumber = new Cell('Điện thoại');
this.$linkFb = new Cell('Link Facebook');
this.$service = new Cell('Dịch vụ đăng ký');
this.$branch = new Cell('Chi nhánh');
this.$script = new Cell('Kịch bản');
this.$interactive = new Cell('Tương tác');
this.$note = new Cell('Ghi chú');
this.$tbody = document.createElement('div');
this.$tbody.className = 'dataTable__content';
this.getAllLeads()
}
3. Code PageSplit
3.9 Cấu trúc thư mục / Tạo file: src/components/LeadList.js
getAllLeads = () => {
this.$tbody.innerHTML = ''
for (let i = 0; i < this.data.length; i++) {
this.$item = new LeadItem({
...this.data[i]
})
this.$tbody.appendChild(this.$item.render())
}
return this.$tbody
}
render() {
this.$container.appendChild(this.$theadTr)
this.$container.appendChild(this.$tbody)
this.$theadTr.appendChild(this.$name.render());
this.$theadTr.appendChild(this.$phoneNumber.render());
this.$theadTr.appendChild(this.$linkFb.render());
this.$theadTr.appendChild(this.$service.render());
this.$theadTr.appendChild(this.$branch.render());
this.$theadTr.appendChild(this.$script.render());
this.$theadTr.appendChild(this.$interactive.render());
this.$theadTr.appendChild(this.$note.render());
return this.$container
}
}
export default LeadList
3. Code PageSplit
3.10 Cấu trúc thư mục / Tạo file: src/components/Pagination.js
class Pagination {
constructor({ count, index, setIndex, getAllData }) {
this.index = index //Vị trí hiện tại
this.getAllData = getAllData // hàm lấy tất cả danh sách
this.setIndex = setIndex // hàm set vị trí index
this.dataLength = count // đếm số phần tử của pagination
this.limit = this.dataLength < 6 ? this.dataLength : 6 // giới hạn số phần tử của pagination
this.count = this.limit + this.index - 1 >= this.dataLength ? this.dataLength : this.limit + this.index - 1 // giới hạn phần tử lớn nhất được render của pagination
this.$container = document.createElement('ul')
this.$container.classList.add('pagination')
//nút về đầu
this.$preBtnBegin = document.createElement('li')
this.$preBtnBegin.className = `pagination__item ${this.index <= 1 || this.dataLength === 0 ? 'd-none' : ''}`
this.$preBtnBegin.addEventListener('click', () => {
this.prePageBegin()
})
this.$preBtnBegin.innerHTML = '««'
3. Code PageSplit
3.10 Cấu trúc thư mục / Tạo file: src/components/Pagination.js
//nút Quay lại
this.$preBtn = document.createElement('li')
this.$preBtn.className = `pagination__item ${this.index <= 1 || this.dataLength === 0 ? 'd-none' : ''}`
this.$preBtn.addEventListener('click', () => {
this.prePage()
})
this.$preBtn.innerHTML = '«'
//nút next
this.$nextBtn = document.createElement('li')
this.$nextBtn.className = `pagination__item ${this.index >= this.dataLength ?'d-none':''}`
this.$nextBtn.addEventListener('click', () => {
this.nextPage()
})
this.$nextBtn.innerHTML = '»'
//nút next End
this.$nextBtnEnd = document.createElement('li')
this.$nextBtnEnd.className = `pagination__item ${this.index >= this.dataLength ?'d-none':''}`
this.$nextBtnEnd.addEventListener('click', () => {
this.nextPageEnd()
})
this.$nextBtnEnd.innerHTML = '»»'
}
3. Code PageSplit
3.10 Cấu trúc thư mục / Tạo file: src/components/Pagination.js
prePageBegin() {
this.index = 1
this.setIndex(this.index)
this.getAllData()
}
prePage() {
this.index = this.index <= 1 ? 1 : this.index - 1
this.setIndex(this.index)
this.getAllData()
}
nextPage() {
this.index = this.index >= this.limit + this.index - 1 ? this.dataLength : this.index + 1
this.setIndex(this.index)
this.getAllData()
}
nextPageEnd() {
this.index = this.limit + 1
this.setIndex(this.index)
this.getAllData()
}
3. Code PageSplit
3.10 Cấu trúc thư mục / Tạo file: src/components/Pagination.js
render() {
this.$container.innerHTML = ''
this.$container.appendChild(this.$preBtnBegin)
this.$container.appendChild(this.$preBtn)
//render số Phần tử
const numTemp = (number) => {
this.$numBtn = document.createElement('li')
this.$numBtn.className = `pagination__item ${this.index === number ? 'active' : ''}`
this.$numBtn.innerHTML = number;
this.$container.appendChild(this.$numBtn)
this.$numBtn.addEventListener('click', () => {
this.index = number
this.setIndex(this.index)
this.getAllData()
})
}
for (let i = this.count === this.dataLength ? this.count - this.limit + 1 : this.index; i <= this.count; i++) {
numTemp(i)
}
this.$container.appendChild(this.$nextBtn)
this.$container.appendChild(this.$nextBtnEnd)
return this.$container
}
}
export default Pagination