頁是每個網站并不可少的,但是處理往往非常麻煩,雖然有很多的插件可以使用,但復雜度依然不減,今天我們來手敲一個最簡單的實現方式,看夠之后分頁再也不是難題,而且以后用插件也懂原理了。手動擒來!
文章概略:
分頁的原理
分層實現
附贈Git開源代碼
我們先來說下原理吧,分頁就是數據庫的數據太多了,一次性查看不完,分批次查看。一般分頁分為從數據庫處理分頁和在服務器端處理分頁兩大類。
在數據庫分頁就是用多少數據jdbc去多少數據,比如取100條數據,則用sql語句查詢出100條語句就可以了。在服務器分頁就是把數據庫所有數據都取到服務器,然后客戶要多少數據返回多少數據。一般這種方式io要求很高,而且浪費資源。不建議使用,目前開發都是使用第一種方式,編譯好sql語句,在數據庫服務器處理分頁,而且數據庫的服務器一般處理速度很快,利用商用。
分頁無非就是服務器返回“總頁數”和“當前頁數”,然后客戶端(一般是瀏覽器)對應處理。我們分層來寫。
服務器可以采用java,或者php,或者asp等編寫,返回“總頁數”和“當前頁數”。瀏覽器采取想應處理。我們采用javascript和html處理,邏輯判斷交給js,頁面修飾交給css,使用的時候你可以隨時改變,方便快捷。
看下預覽圖(假設每個頁面顯示10個頁數):css代碼:用作美化,你可以改成你喜歡的樣式
/*分頁*/
/*在div paging中的a標簽的屬性,很簡單的css*/
#paging{
width: 80%;
margin: 20px auto 40px auto;
text-align: center;
color: #666666;
font-size: 1.2em;
font-weight: 700;
}
#paging a{
color: #666666;
font-size: 1.2em;
font-weight: 700;
padding:5px 10px;
}
#paging a:hover{
background-color: #FF464E;
color: #F5F5F5;
}
html代碼:
javascritp進行的邏輯判斷,就是用來個document.writer,簡單吧
備注:我是有的是java編寫的,用了ssm框架,而且url是RESTful風格的,你可以改成普通風格的,代碼注釋很詳細,我在這不解釋了。
RESTful風格:http://localhost:8080/youxuan/index/2
普通風格:http://localhost:8080/youxuan/index?page=2
最終的結果:
總頁數小于10頁時(共6頁),全部顯示,訪問第1頁如下:
總頁數大于10,當前頁數小于10時,顯示前10頁,訪問第2頁如下:
總頁數大于10,當前頁數大于10時,我們讓他顯示左右各5頁,但是考慮增加5頁可能超出總頁數。我們增加判斷以后結果如下:
當前頁+5頁沒超出總頁數,顯示當前頁左右各5頁,訪問第10頁如下:
當前頁+5頁超出總頁數,顯示到最后一頁并向前顯示10頁,訪問第20頁(最后一頁)如下:
實現代碼如下:
<script>
/*
分頁:接收參數:總頁數,當前頁數
默認一個頁面顯示10個頁數
可能的情況:
總頁數小于10頁
全部顯示
總頁數大于10頁
當前頁小于10頁,顯示前10頁
當前頁大于10頁,顯示左右各5頁
當前頁數+5頁大于總頁數,顯示到最后一頁
否則顯示左右各5頁
*/
var path="${ pageContext.request.contextPath }";//獲得當前應用的地址現在是 /youxuan
var url=path+"/index";//a標簽的地址
//el表達式取得當前頁和總頁數
var nowPage=${Paging.nowPage};//當前頁
var countPage=${Paging.countPage};//總頁數
var count=10;//頁面顯示多少記錄,默認每頁顯示10個記錄
//判斷“首頁”是否顯示
if(nowPage>1){
document.writeln(" <a href=\""+url+"/1\">首頁</a>");//采用RESTful格式url
}
//總頁數小于10頁,顯示全部頁
if(countPage<=count){
for (var i=1;i<=countPage;i++) {
document.writeln(" <a href=\""+url+"/"+i+"\">"+i+"</a>");//采用RESTful格式url
}
}else{
//總頁數大于10頁
//當前頁小于10頁,顯示前10頁
if(nowPage<count){
for (var i=1;i<=count;i++) {
document.writeln(" <a href=\""+url+"/"+i+"\">"+i+"</a>");//采用RESTful格式url
}
//顯示省略號和最后一頁
document.writeln("...<a href=\""+url+"/"+countPage+"\">"+countPage+"</a>");
}else{
//當前頁數大于等于10頁,左右各顯示5頁
if (nowPage <=countPage) {
//當前頁+5大于總頁數,顯示到最后一頁,顯示前10頁
if (nowPage + 5 >=countPage) {
for (var i=nowPage - 10; i <=countPage; i++) {
document.writeln(" <a href=\"" + url + "/" + i + "\">" + i + "</a>");//采用RESTful格式url
}
} else {
//當前頁+5小于總頁數,左右各顯示5頁
for (var i=nowPage - 5; i <=nowPage + 5; i++) {
document.writeln(" <a href=\"" + url + "/" + i + "\">" + i + "</a>");//采用RESTful格式url
}
//顯示省略號和最后一頁
document.writeln("...<a href=\"" + url + "/" + countPage + "\">" + countPage + "</a>");
}
}
}
}
//判斷尾頁是否顯示
if(nowPage<countPage){
document.writeln(" <a href=\""+url+"/"+countPage+"\">尾頁</a>");
}
</script>
最好我們最好加個“跳轉到第幾頁的功能”,如圖實現代碼:
到<input type="number" id="page" style="width: 80px;"/>頁
<input type="button" onclick="goPage()" value="轉到" style="background-color: #6c6c6c;padding: 6px; color: #F5F5F5;border: 0"/>
</div>
<script>
//跳轉到第幾頁
function goPage() {
var page=document.getElementById("page").value;
var type=/^[1-9]+$/;
var re=new RegExp(type);
if (page.match(re)==null) {
//輸入格式錯誤
alert("親,頁數一個正整數哦~");
}else {
//判斷是否大于總頁數
if(page>countPage){
alert("親,總共只有"+countPage+"頁呢~");
}else {
window.location.href=url+"/"+page;
}
}
}
</script>
這個這么簡單,就不解釋了吧。
最后,我們說一下后臺實現,我用的是ssm框架,封裝了一個分頁的bean,代碼如下
package com.youxuan.util;
/**
* Created by 兩毛五哥哥 on 2016/8/26.
* 分頁工具類
*/
public class Paging {
private int countDate;//總數據
private int countPage;//總頁數
private int nowPage;//當前頁數
private int pageCount;//每頁顯示多少數據
/**
* 構造函數
* @param countDate
* @param pageCount
* @param nowPage
*/
public Paging(int countDate,int pageCount,int nowPage){
this.countDate=countDate;
this.pageCount=pageCount;
this.nowPage=nowPage;
if(countDate%pageCount==0){
this.countPage=countDate/pageCount;
}else {
this.countPage=countDate/pageCount+1;
}
}
/**
* 構造函數,默認每頁顯示100條數據
* @param countDate
* @param nowPage
*/
public Paging(int countDate,int nowPage){
this(countDate,100,nowPage);
}
public int getCountDate() {
return countDate;
}
public void setCountDate(int countDate) {
this.countDate=countDate;
}
public int getCountPage() {
return countPage;
}
public void setCountPage(int countPage) {
this.countPage=countPage;
}
public int getNowPage() {
return nowPage;
}
public void setNowPage(int nowPage) {
this.nowPage=nowPage;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount=pageCount;
}
}
然后再servlet(controller)中返回這個封裝的對象。你可以不用封裝也行,我覺的這樣可移植性好,下次做項目直接拿來用了。這個項目我做完會開源貢獻的,喜歡的點個贊吧。
最后:git代碼下載地址:https://git.oschina.net/lovepeng/share-for-you.git
@兩毛五哥哥,90逗逼程序員,歡迎騷擾
列表顯示數據時,分頁顯示是必不可少的功能,活不多說,直接干貨拿走,django提供了一個分頁器Paginator,下面的例子說明如何使用它。
1,寫一個帶分頁功能的查詢方法
編輯 myweb\web\views.py文件,加入如下代碼
from models import Tasks
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.views.decorators import csrf
#任務列表
def task_list(request):
contact_list=Tasks.objects.all().order_by('-task_start_date')
#每頁顯示25條
paginator=Paginator(contact_list, 25)
page=request.GET.get('page')
try:
contacts=paginator.page(page)
except PageNotAnInteger:
contacts=paginator.page(1)
except EmptyPage:
contacts=paginator.page(paginator.num_pages)
return render(request, 'taskList.html', {'contacts': contacts})
這里是將數據返回到前端頁面 taskList.html頁面。
2,前端頁面獲取并顯示數據
在myweb\web\templates目錄新建一個taskList.html文件,內容如下:
{% extends 'base.html' %}
{% block content %}
<table class="tableList">
<thead>
<tr>
<th>任務名稱</th>
<th>操作者</th>
<th>任務描述</th>
<th>開始日期</th>
<th>結束日期</th>
<th>任務評價</th>
</tr>
</thead>
<tbody>
{% if contacts.paginator.count > 0 %}
{% for contact in contacts %}
<tr>
<td> {{ contact.task_name }} </td>
<td> {{ contact.task_user }} </td>
<td> {{ contact.task_describe }}</td>
<td> {{ contact.task_start_date }} </td>
<td> {{ contact.task_end_date }} </td>
<td> {{ contact.task_result }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="10" align="center">沒有任務數據</td>
</tr>
{% endif %}
</tbody>
</table>
{# 分頁HTML代碼 #}
<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}">上一頁</a>
{% endif %}
<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
{% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">下一頁</a>
{% endif %}
</span>
</div>
{% endblock %}
3,URL映射
編輯urls.py文件,加入:
url(r'^tasklist/', views.task_list),
要涉及到數據查詢,通常我們都會進行分頁查詢。
假設你的表中有上百萬條記錄,不分頁的話,我們不可能一次性將所有數據全部都載入到前端吧,那前后端都早就崩潰了。
Spring 和 Vue 都提供了開箱即用的分頁功能。
Spring 主要用來處理后端的分頁查詢,VUE 主要在前端展示頁面和進行下一個頁面的查詢。
有關后端 Spring 如何進行分頁查詢的方法,請參考:Spring Data @Repository 的分頁查詢 中的文章。
如果你配置得當,Spring 會將整個查詢的頁面信息發送給前端。
比如我們說的這一部分,在這部分中,我們會知道總共查詢的記錄有多少,每一頁的大小,一共有多少頁,當前是第幾頁等分頁最重要的信息。
VUE 的前端可以用 Pagination 這個組件 Pagination | Components | BootstrapVue
我們直接在前端調用模板,將參數設置進來就完成了。
代碼可以精簡到只有下面幾句話:
<b-pagination
v-model="pagedData.number"
:total-rows="pagedData.totalElements"
:per-page="pagedData.size"
@click="pageSearch(pagedData.number -1)"
class="pagination pagination-rounded justify-content-end mb-2"
></b-pagination>
不用重復做無用的事情了。
第一個參數是當前的頁面是第幾頁。
第二個參數為一共有多少條記錄。
第三個參數為當前分頁的頁面大小。
第四個參數為,如果頁碼被單擊了,我們會觸發一個什么樣的函數,通常這個函數就是通過 AJAX 的調用到后臺再獲取一次數據。
是不是簡單到令人發指。
如果沒有這個模板的話,我們需要手寫分頁,還要算頁面編碼,真心沒必要。
如果想使用不同的 CSS 的話,在分頁模板中加入自己的 CSS 就可以了。
我們的分頁效果為
頁面看起來還非常干凈喔。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。