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