AngularJs+Spring MVC实现分页小结

我是AngualrJs菜鸟,所以特别感谢大神用AngularJs创建自己的Grid–分页组件 tm.pagination.js,帮我实现了这篇博客中最核心的部分。我主要写一下一些细节过程[[大神开源代码地址请戳我]]
大概实现效果是这样的:
这里写图片描述

前端代码是这样子的:

<!doctype html>
<html ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/king/resources/bootstrap-3.3.7/css/bootstrap.min.css">
    <script src="/king/resources/angular-1.6.4/angular-1.6.4/angular.min.js"></script>
    <script src="/king/resources/pagination/tm.pagination.js"></script>
    <style>
        .page-list .pagination {float:left;}
        .page-list .pagination span {cursor: pointer;}
        .page-list .pagination .separate span{cursor: default; border-top:none;border-bottom:none;}
        .page-list .pagination .separate span:hover {background: none;}
        .page-list .page-total {float:left; margin: 25px 20px;}
        .page-list .page-total input, .page-list .page-total select{height: 26px; border: 1px solid #ddd;}
        .page-list .page-total input {width: 40px; padding-left:3px;}
        .page-list .page-total select {width: 50px;}
    </style>
</head>

<body ng-controller="testController">
<div>   
     <div class="container">
        <div class="row" >
            <h1>查询列表页</h1>
            <div class="col-lg-3">
                <p class="lead">ID:</p>
                <input type="text" class="form-control " ng-model="User.id">
            </div>
            <div class="col-lg-3">
                <p class="lead">Name:</p>
                <input type="text" class="form-control " ng-model="User.username">
            </div>
            <div class="col-lg-3">
                <p class="lead">Age:</p>
                <input type="text" class="form-control " ng-model="User.password">
            </div>
            <div class="col-lg-3">
                <button class="btn btn-default" ng-click="queryUser()">查询</button>
            </div>
        </div>
           <br><br>
           <table class="table" >
               <thead>
                <tr>
                    <td class="active">ID</td>
                    <td class="success">USERNAME</td>
                    <td class="warning">PASSWORD</td>
                    <td class="danger">其他的</td>
                    <td class="success">操作</td>
                </tr>
              </thead>
              <tbody>
                  <tr ng-repeat="x in Users">
                      <td class="active">{{x.id}}</td>
                      <td class="success">{{x.username}}</td>
                      <td class="warning">{{x.password}}</td>
                      <td class="danger">{{x.username}}</td>
                      <td class="success" ng-click="deleteThis()"> 删除</td>
                  </tr>
              </tbody>
            </table>
            <tm-pagination conf="paginationConf"></tm-pagination>
        </div>
</div>
<!-- <button class="btn btn-default" ng-click="reGetProducts()">请求</button> -->

<script>
    angular.module('myApp', ['tm.pagination']).controller('testController', function($scope, $http){

        // 配置分页基本参数
        $scope.paginationConf = {
                currentPage: 1,
                itemsPerPage: 10,
                perPageOptions: [10, 20, 24, 30, 40, 50,100]
        };
        //第一次进来取count和data
        $http.post("http://localhost:8080/king/userController/both").then(function(result){
            $scope.paginationConf.totalItems=result.data.count;
            $scope.Users = result.data.data;
        });

        // 分页时候触发 获取数据条目
        var reGetUsers = function(){
            // 发送给后台的请求数据 
            //每页条数
            var max= $scope.paginationConf.itemsPerPage;
            //偏移量
            var offset= ($scope.paginationConf.currentPage-1)*max;

            $scope.User={
                offset : offset,
                max : max
            };
            $http({
                method: 'POST',
                params: $scope.User, 
                url: 'http://localhost:8080/king/userController/both'
            }).then(function(result){
                // 变更产品条目
                $scope.Users = result.data.data;
            });
        };

        // 通过$watch currentPage和itemperPage 当他们一变化的时候,重新获取数据条目
         $scope.$watch('paginationConf.currentPage + paginationConf.itemsPerPage', reGetUsers);
        //查询触发
         $scope.queryUser = function(){
             $http({
                 method: 'POST',
                 params: $scope.User, 
                 url: 'http://localhost:8080/king/userController/both'
             }).then(function (result) {  //正确请求成功时处理  
                $scope.paginationConf.totalItems=result.data.count;
                $scope.Users = result.data.data;
            }).catch(function (result) { //捕捉错误处理  
                alert(result.data.Message);  
            });  
         };

    })
</script>
</body>
</html>

首先为了项目考虑,前端只能用html,这导致了第一个问题,Spring MVC配置无法访问静态的html文件。我是这么解决的:

<!-- 在web.xml中加入下面代码,表示对 下列静态资源不拦截。 -->
     <servlet-mapping>   
         <servlet-name>default</servlet-name>  
         <url-pattern>*.html</url-pattern>  
     </servlet-mapping>  
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpg</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>

注意:上面这段代码必须写在DispatcherServlet前面,表示不用你管我。
现在可以访问到我们的页面了,第二个问题出现了:

 @RequestMapping(value="/display")
     public ModelAndView toExitPage(HttpServletRequest request,
             HttpServletResponse response)throws Exception{
         Map<String, Object> model = new HashMap<String, Object>();
         return new ModelAndView("AngularJs/newpagination",model);
     }

通过RequestMapping注解配置找到这里,ModelAndView只返回了视图,并没有携带数据。因为html是静态的,无法通过el表达式接收${数据}。所以我只好加载完页面后,立即ajax异步请求一次。就是这一段代码的作用:

$http.post("http://localhost:8080/king/userController/both").then(function(result){
            $scope.paginationConf.totalItems=result.data.count;
            $scope.Users = result.data.data;
        });

那么后台Controller里是怎么写的呢?

@RequestMapping(value="/both", method={RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public Map<String, Object> queryBoth(User user, HttpServletRequest request) {
        List<User> list = new ArrayList<User>();
        list = userService.getByUser(user);
        Map<String, Object> model=new HashMap<String, Object>();
        model.put("data", list);
        user.setMax(null);
        Integer totalItems=userService.getByUser(user).size();
        model.put("count", totalItems);
        return model;
    }

这段代码主要做了两件事,一是取要展示的数据,存进list,二是计算数据总量(给分页框架用)。可能会有人说,totalItems取list.size()不就可以了。是不可以的,因为list是分页查询的,它的size最多为每页的条数,这就是为什么要user.setMax(null)。剩下的就是AngualrJs在前端取数据应用和展示了,前面代码里写的很清楚,就不说了。

基本的流程操作完成了,说一下大神框架的应用细节。
1 需要显示的配置分页基本参数,可以把这一段封装在tm.pagination.js文件里。

// 配置分页基本参数
        $scope.paginationConf = {
                currentPage: 1,
                itemsPerPage: 10,
                perPageOptions: [10, 20, 24, 30, 40, 50,100]
        };
link: function(scope, element, attrs) {

            // 封装进来 配置分页基本参数
            scope.conf = {
                    currentPage: 1,
                    itemsPerPage: 10,
                    perPageOptions: [10, 20, 24, 30, 40, 50,100]
            };
            var conf = scope.conf;

2 不太懂的地方,为什么点击分页的时候,会监测到paginationConf.currentPage、paginationConf.itemsPerPage这两个参数发生变化,tm.pagination.js里的代码是怎么和这两个参数对应起来的。
下午回来自答一波:因为用了双向绑定。

<tm-pagination conf="paginationConf"></tm-pagination>

angular.module('tm.pagination', []).directive('tmPagination',[function(){
    return {
        /*
         1.restrict
            (字符串)可选参数,指明指令在DOM里面以什么形式被声明;取值有:
            E(元素),A(属性),C(类),M(注释),其中默认值为A;
            当然也可以两个一起用,比如EA.表示即可以是元素也可以是属性。
         */
        restrict: 'EA',
        /*
         * template(字符串或者函数)可选参数,可以是:
            (1)一段HTML文本
            (2)一个函数,可接受两个参数tElement和tAttrs
         */
        template: '<div class="page-list">' +
            '<ul class="pagination" ng-show="conf.totalItems > 0">' +
            '<li ng-class="{disabled: conf.currentPage == 1}" ng-click="prevPage()"><span>&laquo;</span></li>' +
            '<li ng-repeat="item in pageList track by $index" ng-class="{active: item == conf.currentPage, separate: item == \'...\'}" ' +
            'ng-click="changeCurrentPage(item)">' +
            '<span>{{ item }}</span>' +
            '</li>' +
            '<li ng-class="{disabled: conf.currentPage == conf.numberOfPages}" ng-click="nextPage()"><span>&raquo;</span></li>' +
            '</ul>' +
            '<div class="page-total" ng-show="conf.totalItems > 0">' +
            '每页<select ng-model="conf.itemsPerPage" ng-options="option for option in conf.perPageOptions " ng-change="changeItemsPerPage()"></select>' +
            '/共<strong>{{ conf.totalItems }}</strong>条 ' +
            '跳转至<input type="text" ng-model="jumpPageNum" ng-keyup="jumpPageKeyUp($event)"/>页' +
            '</div>' +
            '<div class="no-items" ng-show="conf.totalItems <= 0">暂无数据</div>' +
            '</div>',
        replace: true,
        /*
         * 布尔值或者对象,可选参数,默认值为false,表示继承父级作用域。
         * 如果值为true,表示继承父作用域,并创建自己的作用域(子作用域)
         * 如果为对象,{},则表示创建一个全新的隔离作用域。
         * 当我们将scope的值设置为{}时,没办法从父级作用域中继承到color的值了。
         */
        scope: {
            //使用'='进行双向绑定 (使用@来进行单向文本(字符串)绑定)
            conf: '='
        },
 // 通过$watch currentPage和itemperPage 当他们一变化的时候,重新获取数据条目
         $scope.$watch('paginationConf.currentPage + paginationConf.itemsPerPage', reGetUsers);

3 reGetUsers函数,要自己显示的计算max和offset。太low了,是自己的代码能力问题,肯定能封装一下的。

4 点击查询的时候,函数代码和reGetUsers函数是一样的,但是我还没学会在AngularJs中怎么复用函数。

总结:虽然算是成功了,但是有许多细节上的问题可以优化,希望各路大神指出不足之处和可以改进的地方。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值