Vue2.0+ElementUI+PageHelper實現(xiàn)的表格分頁功能
前言
最近做了一些前端的項目,要對表格進行一些分頁顯示。表格分頁的方法有很多,從宏觀上來說分為物理分頁和邏輯分頁,由于邏輯分頁(即前端分頁)的做法是將數(shù)據(jù)全部緩存,然后分頁顯示,這樣在數(shù)據(jù)量較大的時候會對瀏覽器的速度產(chǎn)生影響,所以考慮之后我使用了后端分頁,后端分頁的特點是對當前頁的數(shù)據(jù)進行請求,每次當頁碼變化或者每頁數(shù)據(jù)量變化的時候,就重新發(fā)一次請求。這里所用到的技術主要有以下幾種:
- Spring
- SpringMVC
- Mybatis
- VueJS 2.0
- ElementUI
后端數(shù)據(jù)庫用的是Mysql,其實使用其他的數(shù)據(jù)庫也可以,因為PageHelper插件里有對于各個數(shù)據(jù)庫的兼容。PageHelper的本質(zhì)是插入一個Interceptor,在mybatis的sql語句執(zhí)行之前進行分頁處理,本質(zhì)上是加了兩個limit的參數(shù)。對于PageHelper的配置和用法,請參考Spring + Mybatis 使用 PageHelper 插件分頁這篇文章,這里不再贅述。
前端所使用的是最近很火的vuejs框架2.0,這是一個mvvm架構的框架,類似于AngularJS,但是更加輕量。UI框架使用的是由餓了么團隊推出的elementUI框架,這是一款基于vuejs的框架,正好和我們的前端框架完美結合,并且封裝了很多組件,開發(fā)起來很方便。
下面就是這個Demo的截圖,實現(xiàn)了基本的增刪改查功能,表格排序是elementUI的表格控件里自帶的一個屬性,可以很方便的設置。
正文
下面是程序的截圖,右鍵在新標簽頁中打開圖片可以看得清楚些。

下面來看一下前端的代碼,首先是引入的文件:
<link rel="stylesheet" href="/core/element-ui/lib/theme-default/index.css" rel="external nofollow" >
<script src="./js/jquery-3.1.1.min.js"></script>
<script src="./js/json2.js"></script>
<script src="./js/vue.min.js"></script>
<script src="./js/vue-resource.js"></script>
<script src="./element-ui/lib/index.js"></script>
其中第一行和最后一行是ElementUI的導入包,可以從ElementUI官網(wǎng)下載到源文件引入,也可以直接使用CDN的方式來引入:
<!-- 引入樣式 --> <link rel="stylesheet" rel="external nofollow" > <!-- 引入組件庫 --> <script src="https://unpkg.com/element-ui/lib/index.js"></script>
倒數(shù)第二行vue-resource是vuejs的一個ajax插件,可以通過XMLHttpRequest或JSONP發(fā)起請求并處理響應。簡單的說,就是可以用來發(fā)送ajax請求。
接下來是style樣式
<style>
.el-select .el-input {
width: 110px;
}
.el-table .info-row {
background: #c9e5f5;
}
#top {
background:#20A0FF;
padding:5px;
overflow:hidden
}
</style>
HTML body
<div id="test">
<div id="top">
<span style="float:right;">
<el-button type="text" @click="add" style="color:white">添加</el-button>
<el-button type="text" @click="deletenames" style="color:white">批量刪除</el-button>
</span>
</div>
<br/>
<div style="margin-top:15px">
<el-input placeholder="請輸入內(nèi)容" v-model="criteria" style="padding-bottom:10px;">
<el-select v-model="select" slot="prepend" placeholder="請選擇">
<el-option label="id" value="1"></el-option>
<el-option label="name" value="2"></el-option>
</el-select>
<el-button slot="append" icon="search" v-on:click="search"></el-button>
</el-input>
<el-table
ref="testTable"
:data="tableData"
style="width:100%"
border
:default-sort = "{prop: 'id', order: 'ascending'}"
@selection-change="handleSelectionChange"
@row-click="handleclick"
:row-class-name = "tableRowClassName"
>
<el-table-column
type="selection"
>
</el-table-column>
<el-table-column
prop="id"
label="Id"
sortable
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="name"
label="姓名"
sortable>
</el-table-column>
<el-table-column label="操作">
<template scope="scope">
<el-button
size="small"
type="primary"
@click="handleEdit(scope.$index, scope.row)">編輯</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete(scope.$index, scope.row)">刪除</el-button>
</template>
</el-table-column>
</el-table>
<div align="center">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 30, 40]"
:page-size="pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="totalCount">
</el-pagination>
</div>
</div>
</div>
<footer align="center">
<p>© Vue.js 2.0 + ElementUI分頁Demo</p>
</footer>
接下來是比較重要的創(chuàng)建vue實例。這里使用ES5的寫法。
<script>
var vue = new Vue({
el:"#test",
data: {
//表格當前頁數(shù)據(jù)
tableData: [],
//多選數(shù)組
multipleSelection: [],
//請求的URL
url:'newstu/querystudentbypage',
//搜索條件
criteria: '',
//下拉菜單選項
select: '',
//默認每頁數(shù)據(jù)量
pagesize: 10,
//默認高亮行數(shù)據(jù)id
highlightId: -1,
//當前頁碼
currentPage: 1,
//查詢的頁碼
start: 1,
//默認數(shù)據(jù)總數(shù)
totalCount: 1000,
},
methods: {
//從服務器讀取數(shù)據(jù)
loadData: function(criteria, pageNum, pageSize){
this.$http.get(this.url,{parameter:criteria, pageNum:pageNum, pageSize:pageSize}).then(function(res){
this.tableData = res.data.pagestudentdata;
this.totalCount = res.data.number;
},function(){
console.log('failed');
});
},
//多選響應
handleSelectionChange: function(val) {
this.multipleSelection = val;
},
//點擊行響應
handleclick: function(row, event, column){
this.highlightId = row.id;
},
//編輯
handleEdit: function(index, row) {
this.$prompt('請輸入新名稱', '提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
}).then(({ value }) => {
if(value==''||value==null)
return;
this.$http.post('newstu/update',{"id":row.id,"name":value},{emulateJSON: true}).then(function(res){
this.loadData(this.criteria, this.currentPage, this.pagesize);
},function(){
console.log('failed');
});
}).catch(() => {
});
},
//單行刪除
handleDelete: function(index, row) {
var array = [];
array.push(row.id);
this.$http.post('newstu/delete',{"array":array},{emulateJSON: true}).then(function(res){
this.loadData(this.criteria, this.currentPage, this.pagesize);
},function(){
console.log('failed');
});
},
//搜索
search: function(){
this.loadData(this.criteria, this.currentPage, this.pagesize);
},
//添加
add: function(){
this.$prompt('請輸入名稱', '提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
}).then(({ value }) => {
if(value==''||value==null)
return;
this.$http.post('newstu/add',{"name":value},{emulateJSON: true}).then(function(res){
this.loadData(this.criteria, this.currentPage, this.pagesize);
},function(){
console.log('failed');
});
}).catch(() => {
});
},
//多項刪除
deletenames: function(){
if(this.multipleSelection.length==0)
return;
var array = [];
this.multipleSelection.forEach((item) => {
array.push(item.id);
})
this.$http.post('newstu/delete',{"array":array},{emulateJSON: true}).then(function(res){
this.loadData(this.criteria, this.currentPage, this.pagesize);
},function(){
console.log('failed');
});
},
//改變當前點擊的行的class,高亮當前行
tableRowClassName: function(row, index){
if(row.id == this.highlightId)
{
return 'info-row';
}
},
//每頁顯示數(shù)據(jù)量變更
handleSizeChange: function(val) {
this.pagesize = val;
this.loadData(this.criteria, this.currentPage, this.pagesize);
},
//頁碼變更
handleCurrentChange: function(val) {
this.currentPage = val;
this.loadData(this.criteria, this.currentPage, this.pagesize);
},
},
});
//載入數(shù)據(jù)
vue.loadData(vue.criteria, vue.currentPage, vue.pagesize);
</script>
現(xiàn)在對上述代碼進行一個簡單的解釋,tableData是表格當前頁所顯示的數(shù)據(jù)的數(shù)組,當網(wǎng)頁加載出來后,首先執(zhí)行l(wèi)oadData方法,criteria是當前的搜索條件,默認為空,第二個參數(shù)是當前頁碼,默認為第一頁,第三個參數(shù)為偏移量,即想查詢的數(shù)量,也就是當前每頁所含有的數(shù)據(jù)量。當頁碼或每頁數(shù)據(jù)量改變時都會以這些參數(shù)的新值作為參數(shù)重新調(diào)用這個方法。我們可以看一下Controller的代碼:
@ResponseBody
@RequestMapping(value = "/querystudentbypage", method = RequestMethod.GET)
public Map<String, Object> querystudentbypage(@RequestParam(value="parameter")String parameter,
@RequestParam(value="pageNum")int pageNum, @RequestParam(value="pageSize")int pageSize)
{
Page<Student> page = iNewStudentService.selectStudents(parameter, pageNum, pageSize);
Map<String, Object> map = new HashMap<String, Object>();
map.put("pagestudentdata", page);
map.put("number", page.getTotal());
return map;
}
ce的實現(xiàn)代碼:
public Page<Student> selectStudents(String parameter, int pageNum, int pageSize)
{
Page<Student> page = PageHelper.startPage(pageNum, pageSize);
newstudentMapper.selectStudents(parameter);
return page;
}
mybatis的代碼
<select id="selectStudents" resultMap="NewStudentResultMap">
select id,name from student where id=#{parameter} or name like CONCAT('%',#{parameter},'%')
</select>
注:為了代碼的簡便,這里對用戶的輸入進行了模糊處理,數(shù)據(jù)表中的id字段等于用戶的輸入或name字段包含了用戶的輸入都可以被查詢出來。
從上面的service實現(xiàn)類和mabatis的代碼中可以看出,我們并沒有手動去給sql語句加limit,而是在newstudentMapper.selectStudents(parameter);這句代碼之前加入了Page page = PageHelper.startPage(pageNum, pageSize);這句代碼就是對PageHelper的調(diào)用,不需要去管PageHelper如何去實現(xiàn)(實際是通過Interceptor),只需要這一句代碼就可以做出物理分頁。它會對緊跟在它后面的一個sql查詢起作用,并且返回分頁后的當頁代碼。
Controller中的map我們可以看到put了兩個值,一個是返回的List,另一個是數(shù)據(jù)總量。前端的表格控件會用到這個LIst,而分頁控件會用到這個數(shù)據(jù)總量。注意startPage的參數(shù),第一個是想要請求的頁碼,第二個是請求頁的數(shù)據(jù)量。這兩個要與前端請求時發(fā)送的參數(shù)相對應。
程序的其他基本功能包括添加、修改、刪除、批量刪除等,前端的代碼都做了解釋,后端也只是單純的調(diào)數(shù)據(jù)庫而已,這里就不再貼上后端的代碼。
注:
表格行點擊高亮功能在ElementUI的表格控件中通過添加highlight-current-row屬性可以設置,不過高亮的顏色被封裝到了css文件里。我這里沒有用到這個屬性,而是自定義了一個class的style,當點擊某行時把自定義的style賦給當前行。如果對ElementUI本身的高亮顏色不滿意又不想去改css文件的話,可以像文中這種方式自定義一個行點擊響應。
寫在最后的話
vuejs作為一個前端控件,在最近幾年越來越受歡迎,它的社區(qū)很活躍,同時又有大量的開源項目庫與之配套,詳細列表請參考Vue 開源項目庫匯總。如果將vuejs與開源庫整合使用,將大大提升前端開發(fā)效率,尤其是對于像我這樣對前端并不是很熟悉的后端工程師,也是可以對照著官網(wǎng)上面的教程和例子進行前端開發(fā)。如果使用ES6的寫法,那么模塊化會更加輕松。
ElementUI也是一套很不錯的組件庫,對于我們經(jīng)常用到的表格、表單、時間日期選擇器等常用組件都有著很好的封裝和接口。
PageHelper作為一個國人寫的mybatis分頁插件,有著相當不錯的表現(xiàn),并且支持當前所有的主流數(shù)據(jù)庫,使用起來也很方便。
前端開發(fā)所需要學習的東西并不比后端開發(fā)少多少,而且更需要一個經(jīng)驗的積累,在此記錄一下學習前端開發(fā)的歷程。
到此這篇關于Vue2.0+ElementUI+PageHelper實現(xiàn)的表格分頁功能的文章就介紹到這了,更多相關Vue2.0 ElementUI PageHelper表格分頁內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue點擊input彈出帶搜索鍵盤并監(jiān)聽該元素的方法
今天小編就為大家分享一篇vue點擊input彈出帶搜索鍵盤并監(jiān)聽該元素的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08
淺談webpack SplitChunksPlugin實用指南
這篇文章主要介紹了淺談webpack SplitChunksPlugin實用指南,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09
vue實現(xiàn)動態(tài)顯示與隱藏底部導航的方法分析
這篇文章主要介紹了vue實現(xiàn)動態(tài)顯示與隱藏底部導航的方法,結合實例形式分析了vue.js針對導航隱藏與顯示的路由配置、事件監(jiān)聽等相關操作技巧,需要的朋友可以參考下2019-02-02
Vue?2源碼解析ParseHTML函數(shù)HTML模板
這篇文章主要為大家介紹了Vue?2源碼解析ParseHTML函數(shù)HTML模板詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08

