前端Vue分页及后端PageHelper分页综合运用

  分页显示数据对项目开发中尤为重要,同时能提升用户体验,下面的前端css、js是我引用这篇文章的《使用Vue开发一个分页插件》,我在这个的基础上结合了后端稍微完善了一下,修改了disable的样式,在里面加了pointer-events: none;来防止在首尾页处点击事件仍然生效。

1、前端

  前端使用了vue全局组件的方式做了一个分页的导航栏,总体有四个部分(css样式、js文件写的Vue全局组件、html及html中的vue代码)

  样式:page-nav.css

div.page-nav{
    font-size: 12px;
    font-family:'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
    color: #666;
    user-select: none;
}
div.page-nav ul{
    padding: 0;
    margin:0;
}
div.page-nav ul li{
    display: inline-block;
    min-width:30px;
    min-height:30px;
    border-radius:3px;
    line-height: 30px;
    text-align: center;
    margin: 0 6px;
    cursor: pointer;
}
div.page-nav ul li.active{
    background: #1796e0;
    color:#fff;
}
div.page-nav ul li.disable{
    color: #ccc;
    pointer-events: none;
}

  page-nav.js

Vue.component('page-nav',{
    props:{
        total:{
            type:[Number,String],
            default:0
        },
        pagesize:{
            type:[Number,String],
            default:1
        },
        page:{
            type:[Number,String],
            default:1
        }
    },
    template:'<div class="page-nav">'+
        '<ul>'+
        '<li :class="page==1?\'disable\':\'\'" @click="prev">上一页</li>'+
        '<li :class="page==1?\'disable\':\'\'" @click="toFirst">首页</li>'+
        '<li v-for="item in list"  :class="[item==page?\'active\':\'\']" @click="handleClick">'+
        '{{item}}'+
        '</li>'+
        '<li :class="page==totalCount?\'disable\':\'\'" @click="toEnd">尾页</li>'+
        '<li :class="page==totalCount?\'disable\':\'\'" @click="next">下一页</li>'+
        '<li>总共{{totalCount}}页</li>'+
        '</ul>'+
        '</div>',
    data(){
        return {
            totalCount:0      //总页数
        }
    },
    computed:{
        list(){
            let list=[];
            //计算总页数
            this.totalCount=this.total/this.pagesize;

            //超限控制
            if(this.page<=0){
                this.page=1;
            }
            if(this.page>=this.totalCount){
                this.page=this.totalCount;
            }

            //计算显示页码
            if(this.totalCount>5){
                if(this.page>2&&this.page<this.totalCount-2){
                    list=[this.page-2,this.page-1,this.page,this.page+1,this.page+2];
                }else if(this.page<=2&&this.page>0){
                    for(let i=1;i<=5;i++){
                        list.push(i);
                    }
                }else if(this.page>=this.totalCount-2&&this.page<=this.totalCount){
                    for(let i=4;i>=0;i--){
                        list.push(this.totalCount-i);
                    }
                }
            }else{
                for(let i = 1;i<=this.totalCount;i++){
                    list.push(i);
                }
            }
            return list;
        }
    },

    methods:{
        //页码点击事件
        handleClick(e){
            let page=parseInt(e.target.innerText);
            let {count,total }=this;
            this.$emit('pagechange',{page,count,total});
        },
        //前一页
        prev(e){
            if(!e.target.classList.contains['disable']){
                this.page>1&&this.page--;
                let {page,count,total }=this;
                this.$emit('pagechange',{page,count,total});
            }
        },
        //下一页
        next(e){
            if(!e.target.classList.contains['disable']){
                this.page<this.totalCount&&this.page++;
                let {page,pagesize,total }=this;
                this.$emit('pagechange',{page,pagesize,total});
            }
        },
        //首页
        toFirst(){
            let {page,pagesize,total }=this;
            this.$emit('pagechange',{page:1, pagesize, total});
        },
        //尾页
        toEnd(){
            let {page,pagesize,total }=this;
            this.$emit('pagechange',{page:this.totalCount, pagesize, total});
        }
    }
});

  html:

<div v-if="users != null">
    <page-nav :page="startPage" :pagesize="pageSize" :total="total" @pageChange="pageChange"></page-nav>
</div>

  html中部分vue代码:

    new Vue({
        el: '#app',
        data() {
            return {
                url: 'http://localhost:8080/',
                users: null,
                user: {
                    id: null,
                    name: '',
                    age: null,
                    sex: ''
                },
                startPage: 1,
                pageSize: 5,
                total: 30,
                isSearch: false
            }
        },
        methods: {
            queryUser: function () {
                var _this = this;
                axios.get(_this.url + 'queryUser', {
                    params: {
                        // 这里我把无条件查找和条件查找放一起了,所以这里传一个对象到后端,这句无关紧要
                        user: JSON.stringify(_this.user),
                        // 传起始页跟页面大小到后端
                        startPage: _this.startPage,
                        pageSize: _this.pageSize
                    }
                })
                    .then(function (response) {
                        // 获取回传的user列表
                        _this.users = response.data.users.list;
                        // 我在后台传了一个msg
                        _this.msg = response.data.msg;
                        // 总记录数(用了pageHelper后在返回的response中包含了记录数信息:total)
                        _this.total = response.data.users.total;
                        console.log(response);
                    })
                    .catch(function (err) {
                        console.log(err);
                    })
            },
            pageChange(e) { // 点击上一页下一页时改变分页导航的样式,同时查询下一条记录
                this.page = e.page;
                this.startPage = this.page;
                this.queryUser();
            }
        },
        created() {
            this.queryUser();
        }
    });

  效果:
在这里插入图片描述

  注:在不知道参数怎么获取时可以打开控制台,在控制台的打印信息即可看到,如下

在这里插入图片描述


2、后端

  上面前端的代码就写完了,接下来是后端的代码,这里我是用了SpringBoot来写的。

  首先是Controller(控制层),参数是前端传过来的对象Json字符串、起始页及页面大小,返回值是Map(我在实现层ServiceImpl中用了Map来存储要返回前端的数据信息)

import com.exam.yezhihu.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * @Author: yzh
 * @Description:
 * @Date: 2020/9/6 13:17
 * @Version: 1.0
 */
@RestController
public class UserController {

    @Autowired
    UserServiceImpl userService;

    @RequestMapping("queryUser")
    public Map queryUser(@RequestParam("user") String userJson, @RequestParam("startPage") Integer startPage, @RequestParam("pageSize") Integer pageSize) {
        return userService.queryUser(userJson, startPage, pageSize);
    }
}

  下面是ServiceImpl(业务实现层)

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.exam.yezhihu.bean.UserBean;
import com.exam.yezhihu.mapper.UserMapper;
import com.exam.yezhihu.service.UserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: yzh
 * @Description:
 * @Date: 2020/9/6 12:49
 * @Version: 1.0
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Override
    public Map queryUser(String userJson, Integer startPage, Integer pageSize) {
        Map info = new HashMap(2);
        // 将Json字符串通过fastjson转为JSONObject对象
        JSONObject jsonObject = JSONObject.parseObject(userJson);
        // 将JSONObject对象转为StockMesBean实体对象
        UserBean user = JSON.toJavaObject(jsonObject, UserBean.class);
        // 设置起始页跟页面大小
        PageHelper.startPage(startPage, pageSize);
        // 查询的方法一定要紧跟PageHelper.startPage,否则可能会出现一些错误
        List<UserBean> users = userMapper.queryUser(user);
        // 将查到的信息转成PageInfo类型
        PageInfo<UserBean> userList = new PageInfo<>(users);
        if (users.size() == 0) {
            info.put("msg", false);
            info.put("users", null);
        } else {
            info.put("msg", true);
            // 返回的是PageInfo类型的user信息列表,这里就包含了刚刚在浏览器控制台看到的lastPage等信息
            info.put("users", userList);
        }
        return info;
    }
}

  至于Mapper层就是数据访问了,这里就是定义一个接口,在Mapper.xml中查询数据库的数据而已,就不多写了,以上就是前后端实现分页的方法,其实方法不止这一种,在控制台打印的数据我们可以看到,后端传到前端的参数还有是否为第一页(最后一页)、是否存在上一页(下一页),我们还可以通过这些参数来判断并对分页的导航栏进行动态控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值