AngularJs+Spring MVC实现分页小结

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

前端代码是这样子的:


<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">IDtd>
                    <td class="success">USERNAMEtd>
                    <td class="warning">PASSWORDtd>
                    <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>


<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文件。我是这么解决的:


     <servlet-mapping>   
         <servlet-name>defaultservlet-name>  
         <url-pattern>*.htmlurl-pattern>  
     servlet-mapping>  
    <servlet-mapping>
        <servlet-name>defaultservlet-name>
        <url-pattern>*.jpgurl-pattern>
    servlet-mapping>
    <servlet-mapping>
        <servlet-name>defaultservlet-name>
        <url-pattern>*.jsurl-pattern>
    servlet-mapping>
    <servlet-mapping>
        <servlet-name>defaultservlet-name>
        <url-pattern>*.cssurl-pattern>
    servlet-mapping>

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

 @RequestMapping(value="/display")
     public ModelAndView toExitPage(HttpServletRequest request,
             HttpServletResponse response)throws Exception{
         Map model = new HashMap();
         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>«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>»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中怎么复用函数。

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

你可能感兴趣的:(web前端,java)