AngularJs+Spring MVC实现分页小结
2017-08-10 10:00
363 查看
我是AngualrJs菜鸟,所以特别感谢大神用AngularJs创建自己的Grid–分页组件 tm.pagination.js,帮我实现了这篇博客中最核心的部分。我主要写一下一些细节过程[[大神开源代码地址请戳我]]
大概实现效果是这样的:
前端代码是这样子的:
首先为了项目考虑,前端只能用html,这导致了第一个问题,Spring MVC配置无法访问静态的html文件。我是这么解决的:
注意:上面这段代码必须写在DispatcherServlet前面,表示不用你管我。
现在可以访问到我们的页面了,第二个问题出现了:
通过RequestMapping注解配置找到这里,ModelAndView只返回了视图,并没有携带数据。因为html是静态的,无法通过el表达式接收${数据}。所以我只好加载完页面后,立即ajax异步请求一次。就是这一段代码的作用:
那么后台Controller里是怎么写的呢?
这段代码主要做了两件事,一是取要展示的数据,存进list,二是计算数据总量(给分页框架用)。可能会有人说,totalItems取list.size()不就可以了。是不可以的,因为list是分页查询的,它的size最多为每页的条数,这就是为什么要user.setMax(null)。剩下的就是AngualrJs在前端取数据应用和展示了,前面代码里写的很清楚,就不说了。
基本的流程操作完成了,说一下大神框架的应用细节。
1 需要显示的配置分页基本参数,可以把这一段封装在tm.pagination.js文件里。
2 不太懂的地方,为什么点击分页的时候,会监测到paginationConf.currentPage、paginationConf.itemsPerPage这两个参数发生变化,tm.pagination.js里的代码是怎么和这两个参数对应起来的。
下午回来自答一波:因为用了双向绑定。
3 reGetUsers函数,要自己显示的计算max和offset。太low了,是自己的代码能力问题,肯定能封装一下的。
4 点击查询的时候,函数代码和reGetUsers函数是一样的,但是我还没学会在AngularJs中怎么复用函数。
总结:虽然算是成功了,但是有许多细节上的问题可以优化,希望各路大神指出不足之处和可以改进的地方。
大概实现效果是这样的:
前端代码是这样子的:
<!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>«</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中怎么复用函数。
总结:虽然算是成功了,但是有许多细节上的问题可以优化,希望各路大神指出不足之处和可以改进的地方。
相关文章推荐
- Maven + Spring MVC+Mybatis + MySQL +AngularJS + Bootstrap 实现简单微博应用(一)环境搭建
- 使用SpringMVC+Angularjs实现登录功能
- SpringMvc+AngularJS通过CORS实现跨域方案
- SpringMvc+Angularjs 实现多文件批量上传
- Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页示例
- Maven + Spring MVC+Mybatis + MySQL +AngularJS + Bootstrap 实现简单微博应用(三)前后台交互
- Maven + Spring MVC+Mybatis + MySQL +AngularJS + Bootstrap 实现简单微博应用(二)访问数据库
- Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页
- SpringMvc+AngularJS通过CORS实现跨域方案
- SpringMvc+AngularJS通过CORS实现跨域方案
- Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页
- bootstrap + angularjs + springmvc + mybatis框架之加载log4j日志
- springmvc+jpa实现分页的两种方式
- Spring MVC+MediaElement.js实现在WEB上播放MP4并支持拖移播放
- angularjsFileUpload+Springmvc上传文件
- Angular.js+Bootstrap实现表格分页
- ajaxfileupload.js+springMVC实现无刷新文件上传
- SpringMVC+ajaxfileupload.js实现文件无刷新上传
- Maven+Mybatis+Spring+SpringMVC实现(oracle)分页查询(附源码)
- 整合开发 Angular2 + Bootstrap4 + Nodejs + Eclipse +Spring + SpringMVC +Mybatis