基于angularjs的分页实现
抱着学习angularjs的想法,写了一个简单的分页指令,重在用angularjs实现分页的各种功能,没有太关注样式,所以说东西确实太丑。
分页.jpg
主要功能:
1、显示总页数
2、每页显示数量
3、首页/尾页
4、上一页/下一页
5、可切换页数,根据选择变化
6、跳转指定页数
原则:
指令负责dom变化渲染
控制器负责数据变化
由于操作行为都发生在指令上,控制器数据的变化需要根据指令的状态决定,所以它们之间就需要同步几个状态:
pageRange 可切换页数的最大范围
itemTotal 数据数组的总长度
pageActive 当前激活的页数
divLength 每页显示数量
除了第一个pageRange和itemTotal从控制器传入就不会发生改变,其他两个会根据指令操作改变状态,并且同步回控制器。
在index.html以属性的方式调用指令,传入参数:
<div pagination page-range="pageRange" item-total="itemTotal" page-active="pageActive" div-length="divLength"></div>
在index.js注册控制器和指令:
(function () {
angular
.module("app", [])
.controller("ctrl", ["$scope", function ($scope) {...}])
.directive("pagination", function () {...})
})();
控制器内部定义:
.controller("ctrl", ["$scope", function ($scope) {
// 测试数据
$scope.items = [];
for(let i=0; i<200; i++){
$scope.items.push({
id:i,
name: "haha"+i
})
}
//----------------------------------------分页设置-------------------------------------------------------
// 全局配置
let pageConf = {
// 显示页数的最大范围 [3-9]
pageRange: 1,
// 初始选中的页数
initSelect: 1,
// 每页显示的数量
divLength: 10,
};
// 始终不改变的变量
$scope.pageRange= pageConf.pageRange;
// 指令<==>控制器 的变量
$scope.pageActive= pageConf.initSelect;
$scope.divLength= pageConf.divLength.toString();
// 根据测试数据改变
$scope.itemTotal = $scope.items.length;
$scope.$watchGroup(["pageActive", "divLength"], function () {
$scope.pageItems = $scope.items.slice(
($scope.pageActive-1)*parseInt($scope.divLength), $scope.pageActive*parseInt($scope.divLength)
);
});
//----------------------------------------分页设置-------------------------------------------------------
}])
其中最重要的就是,根据指令同步回来的pageActive和divLength重新切分数据:
$scope.$watchGroup(["pageActive", "divLength"], function () {
$scope.pageItems = $scope.items.slice(
($scope.pageActive-1)*parseInt($scope.divLength), $scope.pageActive*parseInt($scope.divLength)
);
});
这要数据切分和dom变化通过两个状态同步,两部分代码逻辑成功解耦在不同模块。
负责dom操作的指令功能:
1、渲染分页组件
.directive("pagination", function () {
return {
restrict: "AE",
replace: true,
templateUrl: "./pagination.html",
scope: {
pageRange: "=pageRange",
itemTotal: "=itemTotal",
pageActive: "=pageActive",
divLength: "=divLength",
},
link: function (scope, element, attributes, controller) {...}
}
})
pagination.html
<div class="pagination">
<div>
<span>共 {{pageLength}} 页</span>
每页
<select ng-model="divLength" ng-change="recompute()">
<option value="{{item}}" ng-repeat="item in items">{{item}}</option>
</select>
条
</div>
<div>
<ul>
<li><a href="javascript:" ng-click="start()" ng-class="{'cantClick': pageActive===1||itemTotal===0}">首页</a></li>
<li><a href="javascript:" ng-click="pre()" ng-class="{'cantClick': pageActive===1||itemTotal===0}">上一页</a></li>
<li ng-repeat="pl in pList"><a href="javascript:" ng-click="render(pl)" ng-class="{'curActive': pageActive===pl}">{{pl}}</a></li>
<li><a href="javascript:" ng-click="next()" ng-class="{'cantClick': pageActive===pageLength||itemTotal===0}">下一页</a></li>
<li><a href="javascript:" ng-click="end()" ng-class="{'cantClick': pageActive===pageLength||itemTotal===0}">尾页</a></li>
</ul>
</div>
<div>
<input type="number" style="width: 60px;" ng-model="pageIndex"/>
<button ng-click="jump(pageIndex)">跳转</button>
</div>
</div>
2、渲染 可切换页数
// 最下层都不做合法性的检验,上层确保输入数据的正确性。
scope.render = function (pageActive) {
// 先清空,再渲染
scope.pList = [];
let range = scope.pageRange>scope.pageLength?scope.pageLength:scope.pageRange;
let offset = Math.floor(scope.pageRange / 2);
if (pageActive - offset <= 1) {
for (let i = 1; i < range + 1; i++) {
scope.pList.push(i);
}
}
else if (pageActive + offset >= scope.pageLength) {
for (let i = scope.pageLength; i > scope.pageLength - range; i--) {
scope.pList.unshift(i);
}
} else {
for (let i = pageActive - offset; i <= pageActive + offset; i++) {
scope.pList.push(i);
}
}
scope.pageActive = pageActive;
scope.pageIndex = pageActive;
};
3、上一页/下一页
scope.pre = function () {
if(scope.pageActive>1){
scope.render(scope.pageActive - 1);
}
};
scope.next = function () {
if(scope.pageActive<scope.pageLength){
scope.render(scope.pageActive + 1);
}
};
4、首页/尾页
scope.start = function () {
if(!(scope.pageActive===1)){
scope.render(1);
}
};
scope.end = function () {
if(!(scope.pageActive===scope.pageLength)){
scope.render(scope.pageLength);
}
};
5、跳转
scope.jump = function(pageActive){
if((typeof scope.pageLength!=="number")||pageActive<1||pageActive>scope.pageLength){
alert(`Please enter a valid page number! range from 1 to ${scope.pageLength}.`);
scope.pageIndex = scope.pageActive;
} else {
scope.render(pageActive);
element.find("button").attr("disabled", "disabled");
}
};
scope.$watch("pageIndex", function (newVal) {
if((typeof newVal!=="number")||newVal === scope.pageActive){
element.find("button").attr("disabled", "disabled");
} else {
element.find("button").removeAttr("disabled");
}
});
6、改变每页显示数量
scope.recompute = function() {
// 重新计算总共多少页
scope.pageLength = Math.ceil(scope.itemTotal / scope.divLength);
// 重置跳转到第一页
scope.render(1);
};
7、初始化
scope.render(scope.pageActive);
完整index.js代码
(function () {
angular
.module("app", [])
.controller("ctrl", ["$scope", function ($scope) {
// 测试数据
$scope.items = [];
for(let i=0; i<200; i++){
$scope.items.push({
id:i,
name: "haha"+i
})
}
//----------------------------------------分页设置-------------------------------------------------------
// 全局配置
let pageConf = {
// 显示页数的最大范围 [3-9]
pageRange: 1,
// 初始选中的页数
initSelect: 1,
// 每页显示的数量
divLength: 10,
};
// 始终不改变的变量
$scope.pageRange= pageConf.pageRange;
// 指令<==>控制器 的变量
$scope.pageActive= pageConf.initSelect;
$scope.divLength= pageConf.divLength.toString();
// 根据测试数据改变
$scope.itemTotal = $scope.items.length;
$scope.$watchGroup(["pageActive", "divLength"], function () {
$scope.pageItems = $scope.items.slice(
($scope.pageActive-1)*parseInt($scope.divLength), $scope.pageActive*parseInt($scope.divLength)
);
});
//----------------------------------------分页设置-------------------------------------------------------
}])
.directive("pagination", function () {
return {
restrict: "AE",
replace: true,
templateUrl: "./pagination.html",
scope: {
pageRange: "=pageRange",
itemTotal: "=itemTotal",
pageActive: "=pageActive",
divLength: "=divLength",
},
link: function (scope, element, attributes, controller) {
// 没有数据
if((typeof scope.itemTotal!=="number")||scope.itemTotal<1){
scope.itemTotal = 0;
element.find("input").attr("disabled", "disabled");
element.find("select").attr("disabled", "disabled");
element.find("button").attr("disabled", "disabled");
return;
}
// 每页显示数量
scope.items = [10, 30, 50];
// 分页列表
scope.pList = [];
// 计算总共多少页
scope.pageLength = Math.ceil(scope.itemTotal / scope.divLength);
// 校验初始scope.pageActive是否合法,不合法重置为1
if((typeof scope.pageActive!=="number")||scope.pageActive<1||scope.pageActive>scope.pageLength){
scope.pageActive = 1;
console.log('Reset pageActive = 1');
}
// 校验初始scope.pageRange是否合法,不合法重置为9
if((typeof scope.pageRange!=="number")||scope.pageRange<2||scope.pageRange>9){
scope.pageRange = 9;
console.log('Reset pageRange = 9');
}
// 最下层都不做合法性的检验,上层确保输入数据的正确性。
scope.render = function (pageActive) {
// 先清空,再渲染
scope.pList = [];
let range = scope.pageRange>scope.pageLength?scope.pageLength:scope.pageRange;
let offset = Math.floor(scope.pageRange / 2);
if (pageActive - offset <= 1) {
for (let i = 1; i < range + 1; i++) {
scope.pList.push(i);
}
}
else if (pageActive + offset >= scope.pageLength) {
for (let i = scope.pageLength; i > scope.pageLength - range; i--) {
scope.pList.unshift(i);
}
} else {
for (let i = pageActive - offset; i <= pageActive + offset; i++) {
scope.pList.push(i);
}
}
scope.pageActive = pageActive;
scope.pageIndex = pageActive;
};
scope.pre = function () {
if(scope.pageActive>1){
scope.render(scope.pageActive - 1);
}
};
scope.next = function () {
if(scope.pageActive<scope.pageLength){
scope.render(scope.pageActive + 1);
}
};
scope.start = function () {
if(!(scope.pageActive===1)){
scope.render(1);
}
};
scope.end = function () {
if(!(scope.pageActive===scope.pageLength)){
scope.render(scope.pageLength);
}
};
scope.jump = function(pageActive){
if((typeof scope.pageLength!=="number")||pageActive<1||pageActive>scope.pageLength){
alert(`Please enter a valid page number! range from 1 to ${scope.pageLength}.`);
scope.pageIndex = scope.pageActive;
} else {
scope.render(pageActive);
element.find("button").attr("disabled", "disabled");
}
};
scope.$watch("pageIndex", function (newVal) {
if((typeof newVal!=="number")||newVal === scope.pageActive){
element.find("button").attr("disabled", "disabled");
} else {
element.find("button").removeAttr("disabled");
}
});
scope.recompute = function() {
// 重新计算总共多少页
scope.pageLength = Math.ceil(scope.itemTotal / scope.divLength);
// 重置跳转到第一页
scope.render(1);
};
// 初始化
scope.render(scope.pageActive);
}
}
})
})();