ZhangYang's Blog

Express + js 分页器

Express+Handlebars实现分页器

安装express.js

1
// npm install express

安装handlebars

1
// npm install express-handlebars

前端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// views/home.handlebars
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example App</title>
</head>
<body>
{{{body}}}
</body>
</html>
// views/layouts/main.handlebars
<h1>Example App: Home</h1>
<nav>
<ol>
<li><a href="?page=1">1</a></li>
<li><a href="?page=2">2</a></li>
<li><a href="?page=3">3</a></li>
<li><a href="?page=4">4</a></li>
<li><a href="?page=5">5</a></li>
</ol>
</nav>
{{#each articles}}
<articel>
<h1>{{title}}</h1>
<p>{{content}}</p>
</articel>
{{/each}}

后端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// server.js
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.get('/', function (req, res) {
let page = req.query.page || 1
let db = [
{title:'标题1',content:'正文1。。。。。'},
{title:'标题2',content:'正文2。。。。。'},
{title:'标题3',content:'正文3。。。。。'},
{title:'标题4',content:'正文4。。。。。'},
{title:'标题5',content:'正文5。。。。。'},
{title:'标题6',content:'正文6。。。。。'},
{title:'标题7',content:'正文7。。。。。'},
{title:'标题8',content:'正文8。。。。。'},
{title:'标题9',content:'正文9。。。。。'},
{title:'标题10',content:'正文10。。。。。'},
{title:'标题11',content:'正文11。。。。。'},
{title:'标题12',content:'正文12。。。。。'},
{title:'标题13',content:'正文13。。。。。'},
{title:'标题14',content:'正文14。。。。。'},
{title:'标题15',content:'正文15。。。。。'},
{title:'标题16',content:'正文16。。。。。'},
{title:'标题17',content:'正文17。。。。。'},
{title:'标题18',content:'正文18。。。。。'},
{title:'标题19',content:'正文19。。。。。'},
{title:'标题20',content:'正文20。。。。。'},
{title:'标题21',content:'正文21。。。。。'},
{title:'标题22',content:'正文22。。。。。'},
{title:'标题23',content:'正文23。。。。。'},
{title:'标题24',content:'正文24。。。。。'},
{title:'标题25',content:'正文25。。。。。'},
{title:'标题26',content:'正文26。。。。。'},
{title:'标题27',content:'正文27。。。。。'},
{title:'标题28',content:'正文28。。。。。'},
{title:'标题29',content:'正文29。。。。。'},
{title:'标题30',content:'正文30。。。。。'},
{title:'标题31',content:'正文31。。。。。'},
{title:'标题32',content:'正文32。。。。。'},
{title:'标题33',content:'正文33。。。。。'},
{title:'标题34',content:'正文34。。。。。'},
{title:'标题35',content:'正文35。。。。。'},
{title:'标题36',content:'正文36。。。。。'},
{title:'标题37',content:'正文37。。。。。'},
{title:'标题38',content:'正文38。。。。。'},
{title:'标题39',content:'正文39。。。。。'},
{title:'标题40',content:'正文40。。。。。'},
{title:'标题41',content:'正文41。。。。。'},
{title:'标题42',content:'正文42。。。。。'},
{title:'标题43',content:'正文43。。。。。'},
{title:'标题44',content:'正文44。。。。。'},
{title:'标题45',content:'正文45。。。。。'},
{title:'标题46',content:'正文46。。。。。'},
{title:'标题47',content:'正文47。。。。。'},
{title:'标题48',content:'正文48。。。。。'},
{title:'标题49',content:'正文49。。。。。'},
{title:'标题50',content:'正文50。。。。。'}
]
let data = {articles:db.slice(10*(page-1),10*page)}
res.render('home',data)
});
app.listen(3000);

分页器的算法

前端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// views/home.handlebars
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example App</title>
</head>
<body>
{{{body}}}
</body>
</html>
// views/layouts/main.handlebars
<nav id="pager" data-total-pages="{{totalPages}}" data-current-page="{{currentPage}}"></nav>
{{ totalPages }} 页 | 当前是第 {{ currentPage }}
{{#each articles}}
<articel>
<h1>{{title}}</h1>
<p>{{content}}</p>
</articel>
{{/each}}
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
{
let $pager = $('#pager')
let pager = $pager[0]
let {totalPages,currentPage} = pager.dataset
totalPages = window.parseInt(totalPages,10)
currentPage = window.parseInt(currentPage,10)
let $ol = $('<ol />')
buttonCount = 10
let start1 = Math.max(currentPage - Math.round(buttonCount / 2),1)
let end1 = Math.min(start1 + buttonCount - 1, totalPages)
let end2 = Math.min(currentPage + Math.round(buttonCount / 2) -1, totalPages)
let start2 = Math.max(end2 - buttonCount + 1,1)
let start = Math.min(start1,start2)
let end = Math.max(end1,end2)
for(let i = start;i<= end;i++){
let $li
if(i === currentPage){
$li = $(`<li><span>${i}</span></li>`)
}else{
$li = $(`<li><a href="?page=${i}">${i}</a></li>`)
}
$ol.append($li)
}
$pager.append($ol)
}
</script>

后端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// server.js
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.get('/', function (req, res) {
let page = req.query.page || 1
let db = new Array()
for (var i = 0; i < 1000; i++) {
db.push({title:`标题${i+1}`,content:`正文${i+1}。。。。`})
}
let data = {
articles:db.slice(10*(page-1),10*page),
totalPages: Math.ceil(db.length / 10),
currentPage: page
}
res.render('home',data)
});
app.listen(3000);

自动分页

前端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// views/home.handlebars
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example App</title>
</head>
<body>
{{{body}}}
</body>
</html>
// views/layouts/main.handlebars
<div id="articles">
{{#each articles}}
<articel>
<h1>{{title}}</h1>
<p>{{content}}</p>
</articel>
{{/each}}
</div>
<div>
<button id=loadMore>加载更多</button>
<button hidden id=noMore>没有更多</button>
</div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
{
let page = 1
$button = $('#loadMore')
$button.on('click',function(){
$.get(`/paged?page=${page+1}`,(response)=>{
let {articles} = response
articles.forEach((article,index)=>{
let $article = $(`<article><h1>${article.title}</h1><p>${article.content}</p></article>`)
$article.appendTo($('#articles'))
})
page += 1
if(response.currentPage >= response.totalPages){
$button.attr('hidden',true).attr('disabled',true)
$('#noMore').attr('hidden',false)
}
})
})
$(window).on('scroll',function(){
let delta = loadMore.getBoundingClientRect().top - document.documentElement.clientHeight
if(delta < 100){
loadMore.click()
}
})
}
</script>

后端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// server.js
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.get('/', function (req, res) {
let page = req.query.page || 1
let db = new Array()
for (var i = 0; i < 1000; i++) {
db.push({title:`标题${i+1}`,content:`正文${i+1}。。。。`})
}
let data = {
articles:db.slice(10*(page-1),10*page),
totalPages: Math.ceil(db.length / 10),
currentPage: page
}
res.render('home',data)
});
app.get('/paged', function (req, res) {
let page = req.query.page || 1
let db = new Array()
for (var i = 0; i < 1000; i++) {
db.push({title:`标题${i+1}`,content:`正文${i+1}。。。。`})
}
let data = {
articles:db.slice(10*(page-1),10*page),
totalPages: Math.ceil(db.length / 10),
currentPage: page
}
res.setHeader('Content-Type','application/json')
res.send(JSON.stringify(data))
});
app.listen(3000);