Vue2.0+ElementUI+PageHelper实现的表格分页

前言

最近做了一些前端的项目,要对表格进行一些分页显示。表格分页的方法有很多,从宏观上来说分为物理分页和逻辑分页,由于逻辑分页(即前端分页)的做法是将数据全部缓存,然后分页显示,这样在数据量较大的时候会对浏览器的速度产生影响,所以考虑之后我使用了后端分页,后端分页的特点是对当前页的数据进行请求,每次当页码变化或者每页数据量变化的时候,就重新发一次请求。这里所用到的技术主要有以下几种:

  • Spring
  • SpringMVC
  • Mybatis
  • VueJS 2.0
  • ElementUI

后端数据库用的是Mysql,其实使用其他的数据库也可以,因为PageHelper插件里有对于各个数据库的兼容。PageHelper的本质是插入一个Interceptor,在mybatis的sql语句执行之前进行分页处理,本质上是加了两个limit的参数。对于PageHelper的配置和用法,请参考joker_zhou写的Spring + Mybatis 使用 PageHelper 插件分页这篇文章,这里不再赘述。

前端所使用的是最近很火的vuejs框架2.0,这是一个mvvm架构的框架,类似于AngularJS,但是更加轻量。UI框架使用的是由饿了么团队推出的elementUI框架,这是一款基于vuejs的框架,正好和我们的前端框架完美结合,并且封装了很多组件,开发起来很方便。 
下面就是这个Demo的截图,实现了基本的增删改查功能,表格排序是elementUI的表格控件里自带的一个属性,可以很方便的设置。

正文

下面是程序的截图,右键在新标签页中打开图片可以看得清楚些。

下面来看一下前端的代码,首先是引入的文件:

<link rel="stylesheet" href="/core/element-ui/lib/theme-default/index.css">
<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官网下载到源文件引入,也可以直接使用CDN的方式来引入:

<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-default/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

倒数第二行vue-resource是vuejs的一个ajax插件,可以通过XMLHttpRequest或JSONP发起请求并处理响应。简单的说,就是可以用来发送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="请输入内容" v-model="criteria" style="padding-bottom:10px;">
<el-select v-model="select" slot="prepend" placeholder="请选择">
<el-option label="id" value=""></el-option>
<el-option label="name" value=""></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>&copy; Vue.js 2.0 + ElementUI分页Demo</p>
</footer>

接下来是比较重要的创建vue实例。这里使用ES5的写法。

<script>
var vue = new Vue({
el:"#test",
data: {
//表格当前页数据
tableData: [], //多选数组
multipleSelection: [], //请求的URL
url:'newstu/querystudentbypage', //搜索条件
criteria: '', //下拉菜单选项
select: '', //默认每页数据量
pagesize: , //默认高亮行数据id
highlightId: -, //当前页码
currentPage: , //查询的页码
start: , //默认数据总数
totalCount: ,
}, methods: { //从服务器读取数据
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==)
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';
}
}, //每页显示数据量变更
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);
}, }, }); //载入数据
vue.loadData(vue.criteria, vue.currentPage, vue.pagesize);
</script>

现在对上述代码进行一个简单的解释,tableData是表格当前页所显示的数据的数组,当网页加载出来后,首先执行loadData方法,criteria是当前的搜索条件,默认为空,第二个参数是当前页码,默认为第一页,第三个参数为偏移量,即想查询的数量,也就是当前每页所含有的数据量。当页码或每页数据量改变时都会以这些参数的新值作为参数重新调用这个方法。我们可以看一下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;
}

还有service的实现代码:

 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>

注:为了代码的简便,这里对用户的输入进行了模糊处理,数据表中的id字段等于用户的输入或name字段包含了用户的输入都可以被查询出来。

从上面的service实现类和mabatis的代码中可以看出,我们并没有手动去给sql语句加limit,而是在newstudentMapper.selectStudents(parameter);这句代码之前加入了Page page = PageHelper.startPage(pageNum, pageSize);这句代码就是对PageHelper的调用,不需要去管PageHelper如何去实现(实际是通过Interceptor),只需要这一句代码就可以做出物理分页。它会对紧跟在它后面的一个sql查询起作用,并且返回分页后的当页代码。 
Controller中的map我们可以看到put了两个值,一个是返回的List,另一个是数据总量。前端的表格控件会用到这个LIst,而分页控件会用到这个数据总量。注意startPage的参数,第一个是想要请求的页码,第二个是请求页的数据量。这两个要与前端请求时发送的参数相对应。

程序的其他基本功能包括添加、修改、删除、批量删除等,前端的代码都做了解释,后端也只是单纯的调数据库而已,这里就不再贴上后端的代码。

注: 
表格行点击高亮功能在ElementUI的表格控件中通过添加highlight-current-row属性可以设置,不过高亮的颜色被封装到了css文件里。我这里没有用到这个属性,而是自定义了一个class的style,当点击某行时把自定义的style赋给当前行。如果对ElementUI本身的高亮颜色不满意又不想去改css文件的话,可以像文中这种方式自定义一个行点击响应。

写在最后的话

vuejs作为一个前端控件,在最近几年越来越受欢迎,它的社区很活跃,同时又有大量的开源项目库与之配套,详细列表请参考Vue 开源项目库汇总。如果将vuejs与开源库整合使用,将大大提升前端开发效率,尤其是对于像我这样对前端并不是很熟悉的后端工程师,也是可以对照着官网上面的教程和例子进行前端开发。如果使用ES6的写法,那么模块化会更加轻松。

ElementUI也是一套很不错的组件库,对于我们经常用到的表格、表单、时间日期选择器等常用组件都有着很好的封装和接口。

PageHelper作为一个国人写的mybatis分页插件,有着相当不错的表现,并且支持当前所有的主流数据库,使用起来也很方便。

前端开发所需要学习的东西并不比后端开发少多少,而且更需要一个经验的积累,在此记录一下学习前端开发的历程。

项目下载地址: https://github.com/tjfy1992/SpringBoot


版权声明:本文为博主原创文章,未经博主允许不得转载。

Vue2.0+ElementUI+PageHelper实现的表格分页的更多相关文章

  1. vue2.0 + Element UI + axios实现表格分页

    注:本文分页组件用原生 html + css 实现,element-ui里有专门的分页组件可以不用自己写,详情见另一篇博客:https://www.cnblogs.com/zdd2017/p/1115 ...

  2. Vue2.0 + Element-UI + WebAPI实践:简易个人记账系统

    最近正在学习Vue2.0相关知识,正好近期饿了么桌面端组件Element-UI发布,便动手做了一款简易个人记账系统,以达到实践及巩固目的. 1.开发环境 Win10 + VS2015 + Sqlser ...

  3. Vue2.0 + ElementUI 手写权限管理系统后台模板(一)——简述

    挤一下: 一开始以为没有多少人用就没建群,但是加我的人太多了,好多问题都是重复的,所以建个群大家互相沟通交流方便点,但是建的有点晚,错过了好多人所以群里人有点少,QQ群: 157216616 小提示 ...

  4. vue2.0+elementUI构建单页面后台管理平台

    git:https://github.com/reg21st/vue2-management-platform 访问:https://reg21st.github.io/vue2-management ...

  5. vue2.0+element-ui(01简单点的单页面)

    前言: 在<Vue.js权威指南>刚出版的时候,自己就作为一名前端粉捧了一把场,可是真是应了那句“出来混,总是要还的“这句话了,那时候信心满满的买来书想要认真研究,最终却还是把它搁浅了.直 ...

  6. Vue实例:vue2.0+ElementUI框架开发pc项目

    开发前准备 vue.js2.0中文,项目所使用的js框架 vue-router,vue.js配套路由 vuex,状态管理 Element,UI框架 1,根据官方指引,构建项目框架 安装vue npm ...

  7. Vue2.0 + ElementUI的+ PageHelper实现的表格分页

    参考博客:http://blog.csdn.net/u012907049/article/details/70237457 借鉴1.controller层编写 2.vue中,axios的写法(总页数等 ...

  8. Vue2.0+ElementUI实现表格翻页的实例

    参考地址: https://www.cnblogs.com/zhouyifeng/p/7706815.html

  9. vue2.0 element-ui中el-upload的before-upload方法返回false时submit()不生效解决方法

    我要实现的功能是在上传文件之前校验是否表格中存在重复的数据,有的话,需要弹窗提示是否覆盖,确认之后继续上传,取消之后,就不再上传. 项目中用的element-ui是V1.4.3 <el-uplo ...

随机推荐

  1. [转]使用RTT(Real-Time Terminal)

    转自http://siever.info/home/hello-world/ Bluetooth Low Energy Logging events with on Nordic’s nRF seri ...

  2. 11.使用ForwardAction实现页面屏蔽。

    转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 我们在jsp页面之间写链接总会是.../xxx.jsp,而如果我们想屏蔽掉具 ...

  3. Delphi Berlin 窗体代码分离风格 回到Delphi7传统风格

    回到Delphi7传统风格 Floating Form Designer You can now detach the form designer in both, VCL and FireMonke ...

  4. IOS HTTP访问端口

    Project dyld_sim raised exception class ENetHTTPClientException with message 'Error -1022 accessing ...

  5. 机器学习入门-随机森林温度预测的案例 1.datetime.datetime.datetime(将字符串转为为日期格式) 2.pd.get_dummies(将文本标签转换为one-hot编码) 3.rf.feature_importances_(研究样本特征的重要性) 4.fig.autofmt_xdate(rotation=60) 对标签进行翻转

    在这个案例中: 1. datetime.datetime.strptime(data, '%Y-%m-%d') # 由字符串格式转换为日期格式 2. pd.get_dummies(features)  ...

  6. AS3中String转换成Boolean

    AS3中, 对布尔值的转换, 规定所有的非空字符串都是true. 下面都不行: var f:Boolean = new Boolean(str); var f:Boolean = str as Boo ...

  7. Docker查看关联容器的卷宗在本机的存储位置

    docker inspect -f {{.Volumes}} volume1

  8. 给pyspark 设置新的环境

    如果是从pysparkshell里面进去,此时已经有了pyspark环境了,所以要加一个:sc.stop() from pyspark import SparkContext, SparkConfsc ...

  9. Eclipse出现错误:The selection cannot be launched,and there are no recent launches

    刚装了eclipse,想写个Java程序测试一下能不能用,结果一run就出现错误,Debug也是同样的错误,错误内容为:the selection cannot be launched,and the ...

  10. GEOquery

    1)介绍 来自NCBI的Gene Expression Omnibus(GEO)作为各种高通量实验数据的公共存储库. 这些数据包括基于单通道和双通道微阵列的实验,测量mRNA,基因组DNA和蛋白质丰度 ...