Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
頁是每個網(wǎng)站并不可少的,但是處理往往非常麻煩,雖然有很多的插件可以使用,但復(fù)雜度依然不減,今天我們來手敲一個最簡單的實(shí)現(xiàn)方式,看夠之后分頁再也不是難題,而且以后用插件也懂原理了。手動擒來!
文章概略:
分頁的原理
分層實(shí)現(xiàn)
附贈Git開源代碼
我們先來說下原理吧,分頁就是數(shù)據(jù)庫的數(shù)據(jù)太多了,一次性查看不完,分批次查看。一般分頁分為從數(shù)據(jù)庫處理分頁和在服務(wù)器端處理分頁兩大類。
在數(shù)據(jù)庫分頁就是用多少數(shù)據(jù)jdbc去多少數(shù)據(jù),比如取100條數(shù)據(jù),則用sql語句查詢出100條語句就可以了。在服務(wù)器分頁就是把數(shù)據(jù)庫所有數(shù)據(jù)都取到服務(wù)器,然后客戶要多少數(shù)據(jù)返回多少數(shù)據(jù)。一般這種方式io要求很高,而且浪費(fèi)資源。不建議使用,目前開發(fā)都是使用第一種方式,編譯好sql語句,在數(shù)據(jù)庫服務(wù)器處理分頁,而且數(shù)據(jù)庫的服務(wù)器一般處理速度很快,利用商用。
分頁無非就是服務(wù)器返回“總頁數(shù)”和“當(dāng)前頁數(shù)”,然后客戶端(一般是瀏覽器)對應(yīng)處理。我們分層來寫。
服務(wù)器可以采用java,或者php,或者asp等編寫,返回“總頁數(shù)”和“當(dāng)前頁數(shù)”。瀏覽器采取想應(yīng)處理。我們采用javascript和html處理,邏輯判斷交給js,頁面修飾交給css,使用的時候你可以隨時改變,方便快捷。
看下預(yù)覽圖(假設(shè)每個頁面顯示10個頁數(shù)):css代碼:用作美化,你可以改成你喜歡的樣式
/*分頁*/
/*在div paging中的a標(biāo)簽的屬性,很簡單的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進(jìn)行的邏輯判斷,就是用來個document.writer,簡單吧
備注:我是有的是java編寫的,用了ssm框架,而且url是RESTful風(fēng)格的,你可以改成普通風(fēng)格的,代碼注釋很詳細(xì),我在這不解釋了。
RESTful風(fēng)格:http://localhost:8080/youxuan/index/2
普通風(fēng)格:http://localhost:8080/youxuan/index?page=2
最終的結(jié)果:
總頁數(shù)小于10頁時(共6頁),全部顯示,訪問第1頁如下:
總頁數(shù)大于10,當(dāng)前頁數(shù)小于10時,顯示前10頁,訪問第2頁如下:
總頁數(shù)大于10,當(dāng)前頁數(shù)大于10時,我們讓他顯示左右各5頁,但是考慮增加5頁可能超出總頁數(shù)。我們增加判斷以后結(jié)果如下:
當(dāng)前頁+5頁沒超出總頁數(shù),顯示當(dāng)前頁左右各5頁,訪問第10頁如下:
當(dāng)前頁+5頁超出總頁數(shù),顯示到最后一頁并向前顯示10頁,訪問第20頁(最后一頁)如下:
實(shí)現(xiàn)代碼如下:
<script>
/*
分頁:接收參數(shù):總頁數(shù),當(dāng)前頁數(shù)
默認(rèn)一個頁面顯示10個頁數(shù)
可能的情況:
總頁數(shù)小于10頁
全部顯示
總頁數(shù)大于10頁
當(dāng)前頁小于10頁,顯示前10頁
當(dāng)前頁大于10頁,顯示左右各5頁
當(dāng)前頁數(shù)+5頁大于總頁數(shù),顯示到最后一頁
否則顯示左右各5頁
*/
var path="${ pageContext.request.contextPath }";//獲得當(dāng)前應(yīng)用的地址現(xiàn)在是 /youxuan
var url=path+"/index";//a標(biāo)簽的地址
//el表達(dá)式取得當(dāng)前頁和總頁數(shù)
var nowPage=${Paging.nowPage};//當(dāng)前頁
var countPage=${Paging.countPage};//總頁數(shù)
var count=10;//頁面顯示多少記錄,默認(rèn)每頁顯示10個記錄
//判斷“首頁”是否顯示
if(nowPage>1){
document.writeln(" <a href=\""+url+"/1\">首頁</a>");//采用RESTful格式url
}
//總頁數(shù)小于10頁,顯示全部頁
if(countPage<=count){
for (var i=1;i<=countPage;i++) {
document.writeln(" <a href=\""+url+"/"+i+"\">"+i+"</a>");//采用RESTful格式url
}
}else{
//總頁數(shù)大于10頁
//當(dāng)前頁小于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{
//當(dāng)前頁數(shù)大于等于10頁,左右各顯示5頁
if (nowPage <=countPage) {
//當(dāng)前頁+5大于總頁數(shù),顯示到最后一頁,顯示前10頁
if (nowPage + 5 >=countPage) {
for (var i=nowPage - 10; i <=countPage; i++) {
document.writeln(" <a href=\"" + url + "/" + i + "\">" + i + "</a>");//采用RESTful格式url
}
} else {
//當(dāng)前頁+5小于總頁數(shù),左右各顯示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>
最好我們最好加個“跳轉(zhuǎn)到第幾頁的功能”,如圖實(shí)現(xiàn)代碼:
到<input type="number" id="page" style="width: 80px;"/>頁
<input type="button" onclick="goPage()" value="轉(zhuǎn)到" style="background-color: #6c6c6c;padding: 6px; color: #F5F5F5;border: 0"/>
</div>
<script>
//跳轉(zhuǎn)到第幾頁
function goPage() {
var page=document.getElementById("page").value;
var type=/^[1-9]+$/;
var re=new RegExp(type);
if (page.match(re)==null) {
//輸入格式錯誤
alert("親,頁數(shù)一個正整數(shù)哦~");
}else {
//判斷是否大于總頁數(shù)
if(page>countPage){
alert("親,總共只有"+countPage+"頁呢~");
}else {
window.location.href=url+"/"+page;
}
}
}
</script>
這個這么簡單,就不解釋了吧。
最后,我們說一下后臺實(shí)現(xiàn),我用的是ssm框架,封裝了一個分頁的bean,代碼如下
package com.youxuan.util;
/**
* Created by 兩毛五哥哥 on 2016/8/26.
* 分頁工具類
*/
public class Paging {
private int countDate;//總數(shù)據(jù)
private int countPage;//總頁數(shù)
private int nowPage;//當(dāng)前頁數(shù)
private int pageCount;//每頁顯示多少數(shù)據(jù)
/**
* 構(gòu)造函數(shù)
* @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;
}
}
/**
* 構(gòu)造函數(shù),默認(rèn)每頁顯示100條數(shù)據(jù)
* @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)中返回這個封裝的對象。你可以不用封裝也行,我覺的這樣可移植性好,下次做項(xiàng)目直接拿來用了。這個項(xiàng)目我做完會開源貢獻(xiàn)的,喜歡的點(diǎn)個贊吧。
最后:git代碼下載地址:https://git.oschina.net/lovepeng/share-for-you.git
@兩毛五哥哥,90逗逼程序員,歡迎騷擾
列表顯示數(shù)據(jù)時,分頁顯示是必不可少的功能,活不多說,直接干貨拿走,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
#任務(wù)列表
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})
這里是將數(shù)據(jù)返回到前端頁面 taskList.html頁面。
2,前端頁面獲取并顯示數(shù)據(jù)
在myweb\web\templates目錄新建一個taskList.html文件,內(nèi)容如下:
{% extends 'base.html' %}
{% block content %}
<table class="tableList">
<thead>
<tr>
<th>任務(wù)名稱</th>
<th>操作者</th>
<th>任務(wù)描述</th>
<th>開始日期</th>
<th>結(jié)束日期</th>
<th>任務(wù)評價</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">沒有任務(wù)數(shù)據(jù)</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),
要涉及到數(shù)據(jù)查詢,通常我們都會進(jìn)行分頁查詢。
假設(shè)你的表中有上百萬條記錄,不分頁的話,我們不可能一次性將所有數(shù)據(jù)全部都載入到前端吧,那前后端都早就崩潰了。
Spring 和 Vue 都提供了開箱即用的分頁功能。
Spring 主要用來處理后端的分頁查詢,VUE 主要在前端展示頁面和進(jìn)行下一個頁面的查詢。
有關(guān)后端 Spring 如何進(jìn)行分頁查詢的方法,請參考:Spring Data @Repository 的分頁查詢 中的文章。
如果你配置得當(dāng),Spring 會將整個查詢的頁面信息發(fā)送給前端。
比如我們說的這一部分,在這部分中,我們會知道總共查詢的記錄有多少,每一頁的大小,一共有多少頁,當(dāng)前是第幾頁等分頁最重要的信息。
VUE 的前端可以用 Pagination 這個組件 Pagination | Components | BootstrapVue
我們直接在前端調(diào)用模板,將參數(shù)設(shè)置進(jìn)來就完成了。
代碼可以精簡到只有下面幾句話:
<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>
不用重復(fù)做無用的事情了。
第一個參數(shù)是當(dāng)前的頁面是第幾頁。
第二個參數(shù)為一共有多少條記錄。
第三個參數(shù)為當(dāng)前分頁的頁面大小。
第四個參數(shù)為,如果頁碼被單擊了,我們會觸發(fā)一個什么樣的函數(shù),通常這個函數(shù)就是通過 AJAX 的調(diào)用到后臺再獲取一次數(shù)據(jù)。
是不是簡單到令人發(fā)指。
如果沒有這個模板的話,我們需要手寫分頁,還要算頁面編碼,真心沒必要。
如果想使用不同的 CSS 的話,在分頁模板中加入自己的 CSS 就可以了。
我們的分頁效果為
頁面看起來還非常干凈喔。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。