layui-laypage模块代码详解

/** layui-v2.4.0 MIT License By https://www.layui.com */
;
layui.define(function(e) {
"use strict";
var a = document,
t = "getElementById",
n = "getElementsByTagName",
i = "laypage",
r = "layui-disabled",
u = function(e) {
var a = this;
// 实例化的时候调用了render方法,layui.laypage不存在,即接口还未对外exports时,index为0
console.log("初次索引:%c" + s.index, "color: red;");
// u是一个构造函数,此处的this将为u实例化后的实例。
// 并且索引在每次render之后增一。
// 并render,!0代表初次render。
a.config = e || {}, a.config.index = ++s.index, a.render(!0)
};
u.prototype.type = function() {
var e = this.config;
console.log("判断分页容器元素是否为对象:%c" + ("object" == typeof e.elem ? 'yes' : 'no'), 'color: blue;');
if ("object" == typeof e.elem) {
console.log("分页容器元素:", e.elem);
// document.getElementById的length是undefin,而jquery的是数值。
return void 0 === e.elem.length ? 2 : 3
} else {
console.log("分页容器元素:%c" + e.elem, "color: blue;");
}
}, u.prototype.view = function() {
var e = this,
a = e.config,
// 判断是否传入了groups,是则对其逻辑或运算,目的转为数字,否则赋默认值5
t = a.groups = "groups" in a ? 0 | a.groups : 5;
// layout 如果已赋值且为对象,使用它,否则为默认["prev", "page", "next"], 其他配置参数也进行逻辑或运算,保证为数字或有默认值
// 逻辑或还能向上取整,3.4214 | 1,对groups进行处理,负数或者大于页码数
a.layout = "object" == typeof a.layout ? a.layout : ["prev", "page", "next"], a.count = 0 | a.count, a.curr = 0 | a.curr || 1, a.limits = "object" == typeof a.limits ? a.limits : [10, 20, 30, 40, 50], a.limit = 0 | a.limit || 10, a.pages = Math.ceil(a.count / a.limit) || 1, a.curr > a.pages && (a.curr = a.pages), t < 0 ? t = 1 : t > a.pages && (t = a.pages), a.prev = "prev" in a ? a.prev : "&#x4E0A;&#x4E00;&#x9875;", a.next = "next" in a ? a.next : "&#x4E0B;&#x4E00;&#x9875;";
var n = a.pages > t ? Math.ceil((a.curr + (t > 1 ? 1 : 0)) / (t > 0 ? t : 1)) : 1,
i = {
prev: function() {
return a.prev ? '<a href="javascript:;" class="layui-laypage-prev' + (1 == a.curr ? " " + r : "") + '" data-page="' + (a.curr - 1) + '">' + a.prev + "</a>" : ""
}(),
page: function() {
var e = [];
if (a.count < 1) return "";
n > 1 && a.first !== !1 && 0 !== t && e.push('<a href="javascript:;" class="layui-laypage-first" data-page="1" title="&#x9996;&#x9875;">' + (a.first || 1) + "</a>");
var i = Math.floor((t - 1) / 2),
r = n > 1 ? a.curr - i : 1,
u = n > 1 ?
function() {
var e = a.curr + (t - i - 1);
return e > a.pages ? a.pages : e
}() : t;
for (u - r < t - 1 && (r = u - t + 1), a.first !== !1 && r > 2 && e.push('<span class="layui-laypage-spr">&#x2026;</span>'); r <= u; r++) r === a.curr ? e.push('<span class="layui-laypage-curr"><em class="layui-laypage-em" ' + (/^#/.test(a.theme) ? 'style="">+ a.theme + ';"' : "") + "></em><em>" + r + "</em></span>") : e.push('<a href="javascript:;" data-page="' + r + '">' + r + "</a>");
return a.pages > t && a.pages > u && a.last !== !1 && (u + 1 < a.pages && e.push('<span class="layui-laypage-spr">&#x2026;</span>'), 0 !== t && e.push('<a href="javascript:;" class="layui-laypage-last" title="&#x5C3E;&#x9875;" data-page="' + a.pages + '">' + (a.last || a.pages) + "</a>")), e.join("")
}(),
next: function() {
return a.next ? '<a href="javascript:;" class="layui-laypage-next' + (a.curr == a.pages ? " " + r : "") + '" data-page="' + (a.curr + 1) + '">' + a.next + "</a>" : ""
}(),
count: '<span class="layui-laypage-count">共 ' + a.count + " 条</span>",
limit: function() {
var e = ['<span class="layui-laypage-limits"><select lay-ignore>'];
return layui.each(a.limits, function(t, n) {
e.push('<option value="' + n + '"' + (n === a.limit ? "selected" : "") + ">" + n + " 条/页</option>")
}), e.join("") + "</select></span>"
}(),
refresh: ['<a href="javascript:;" data-page="' + a.curr + '" class="layui-laypage-refresh">', '<i class="layui-icon layui-icon-refresh"></i>', "</a>"].join(""),
skip: function() {
return ['<span class="layui-laypage-skip">&#x5230;&#x7B2C;', '<input type="text" min="1" value="' + a.curr + '" class="layui-input">', '&#x9875;<button type="button" class="layui-laypage-btn">&#x786e;&#x5b9a;</button>', "</span>"].join("")
}()
};
return ['<div class="layui-box layui-laypage layui-laypage-' + (a.theme ? /^#/.test(a.theme) ? "molv" : a.theme : "default") + '" id="layui-laypage-' + a.index + '">', function() {
var e = [];
return layui.each(a.layout, function(a, t) {
i[t] && e.push(i[t])
}), e.join("")
}(), "</div>"].join("")
}, u.prototype.jump = function(e, a) {
// e是配置或获取到的page元素
console.log("跳转后传入渲染元素:", e);
// render之后执行jump,做的事儿有:
// 1. 初始化则获取输入框值,渲染翻页。
// 2. 对所有a元素进行事件绑定。
// 3. select的事件绑定。
// 4. button的事件绑定。
if (e) {
var t = this,
i = t.config,
r = e.children,
// 点击按钮,即输入后的确认按钮
u = e[n]("button")[0],
// 输入框
l = e[n]("input")[0],
// 下拉菜单
p = e[n]("select")[0],
c = function() {
// 替换掉输入框中非数字部分,确保为数字。
var e = 0 | l.value.replace(/\s|\D/g, "");
// 将curr赋值,并render,即跳转后再次render
// 此处render是实例化对象上的render
// 即点击确认按钮/或初次加载后重新渲染page
e && (i.curr = e, t.render())
};
// 如果a为true,进行render,即标示了input,执行到此
if (a) return c();
// 循环给a元素加第点击事件。
for (var o = 0, y = r.length; o < y; o++)"a" === r[o].nodeName.toLowerCase() && s.on(r[o], "click", function() {
// 获取到页码数,点击的当前页码页码数赋值给配置对象的curr,指示当前所在页码,并重渲染。
var e = 0 | this.getAttribute("data-page");
// 当前页码数小于1或者大于总页码数,则不执行赋值和重渲染。
// 只有既不小于1又不大于总页码数,才赋值和重新渲染。
e < 1 || e > i.pages || (i.curr = e, t.render())
});
// select事件
p && s.on(p, "change", function() {
var e = this.value;
// 当前页码*所选值如果大于总数,则当前页码赋值为总页码/每页显示数的乡下取值。
// 然后重新渲染。
i.curr * e > i.count && (i.curr = Math.ceil(i.count / e)), i.limit = e, t.render()
}),
// 输入后的button确认事件
u && s.on(u, "click", function() {
c()
})
}
}, u.prototype.skip = function(e) {
// e为传入的分页元素对象。
if (e) {
var a = this,
t = e[n]("input")[0];
// chrome下会支持回调传入参数。
t && s.on(t, "keyup", function(t) {
console.log("keyup传入参数:", t);
// keyup的调用对象是t
var n = this.value,
i = t.keyCode;
// 上下左右键,或者输入框值为非数字,则将非数字替换为空
// 如果为确认,执行jump方法,且传入真。。
/^(37|38|39|40)$/.test(i) || (/\D+/.test(n) && (this.value = n.replace(/\D/, "")), 13 === i && a.jump(e, !0))
})
}
},

// 当前render在实例化期间被调用,在s对象中render则成为实例化对象。
u.prototype.render = function(e) {
var n = this,
// 传入的配置对象
i = n.config,
// 获取类型
r = n.type(),
// 生成view
u = n.view();
console.log("判断传入类型:%c" + r, "color: blue;");
// console.log("render获取到的配置:", i);
// 判断是原生js对象还是jquery对象,否则就调用document上的getElementById获取dom元素,
// 将生成的视图赋值给它,跳转回调存在则调用它,也即在render的时候就已经实施了对jump的调用。因此有初次调用一说。
2 === r ? i.elem && (i.elem.innerHTML = u) : 3 === r ? i.elem.html(u) : a[t](i.elem) && (a[t](i.elem).innerHTML = u),
// 此处调用意欲何为?此处jump是用户传入的回调函数,e标示是否第一次,第一次render的时候e是!0,即真
console.log("是否第一次:", e ? '是' : '否'),
i.jump && i.jump(i, e);
// i.index是不断累加的。下面的jump是构造函数上的jump
// 在view方法中以下元素已经被渲染出来了。
var s = a[t]("layui-laypage-" + i.index);
// 执行jump方法并且追加hash
n.jump(s), i.hash && !e && (location.hash = "!" + i.hash + "=" + i.curr), n.skip(s)
};
// e 为传入render的配置对象
// u 为
// function(e) {
// var a = this;
// a.config = e || {}, a.config.index = ++s.index, a.render(!0)
// };
// render 创建了一个实例,返回了索引。
var s = {
render: function(e) {
var a = new u(e);
console.log("laypage原始索引:%c" + s.index, "color: red;");
console.log("laypage配置索引:%c" + a.config.index, "color: red;");
// 返回的index已经是增1以后的。
return a.index
},
index: layui.laypage ? layui.laypage.index + 1e4 : 0,
on: function(e, a, t) {
// e是dom元素对象,a是事件名,t是回调
return e.attachEvent ? e.attachEvent("on" + a, function(a) {
// 此处a是事件对象, 两个的区别是:ie下支持e.srcElement,ff支持e.target。
// 指向触发事件的元素
a.target = a.srcElement, t.call(e, a)
// 禁止冒泡
}) : e.addEventListener(a, t, !1), this
}
};
e(i, s);

/**
* 初次进入页面
* 调用:
* laypage.render({
elem: document.getElementById('laypage'), // 'laypage', $('#laypage'), document.getElementById('laypage');
count: count,
limit: limit,
limits: [5, 10, 20, 30, 50],
curr: page,
groups: 5,
prev: '上一页',
next: '下一页',
first: '首页',
last: '尾页',
layout: ['prev', 'page', 'next', 'first', 'last', 'limit', 'refresh', 'skip', 'count'],
theme: '#1E9FFF',
hash: 'curr',
jump: function (obj, first) {
console.log("jump后的配置:", obj);
if (!first) {
pageTurn(obj.curr, obj.limit);
}
}
})
* 即s对象上的render方法
* 实例化函数u,并将配置作为参数传递给u。
* 将配置对象赋值给是实例化对象。
* 给该配置对象设置索引,为s对象上的index加1。
* exports向外暴露的接口laypage在use或者作为依赖引入的时候,进入内存,初始化index,为0。
* 执行后面扩展到构造函数u上的方法render,传入参数!0,即真,表示第一次。
* 执行原型上的type方法,根据传入配置对象的elem来决定类型,2(原生dom对象),3(jquery对象),undefined(字符串)。
* 构造view html。
* 根据上面的类型赋值给elem元素html。
* 如果用户设置了jump回调,第一次不执行,传入配置对象及是否为第一次,此时为真,毫无疑问。
* 用原生js方法取到当前page元素。
* 执行render里的jump方法。
* 如果该元素存在。
* 获取到该元素的子元素button,input和select。
* 如果参数a为真,仅执行内部函数c,但此时为undefined,不执行c函数。执行c函数的情况是在skip中按下了enter键之后才会执行,前提条件是按下了上下左右方向键或者非数字,执行了input输入框非数字过滤之后,再按下enter键,渲染page。
* 对a元素进行循环绑定click事件,其中回调是获取到a上的data-page页码,比对是否大于总页码或者小于1,对配置对象的curr重新赋值,并执行render。render不传参,因此会执行用户回调。table会重新渲染,page容器的id也会随之而变。
* 对select进行事件绑定,计算curr值及limit值,配置对象发生改变,然后执行无参数render,自然table会被重新渲染,执行用户回调。
* button确认点击事件同理。
* 然后render方法中改变hash值。
* render中执行skip函数,传入page元素。
* 如果page为真,获取到input元素。
* 给他绑定keyup事件,目的是检测按下了上下左右方向键或者非数字,执行input输入框非数字过滤之后,再按下enter键,执行jump。
* 此时jump第二个参数为真。不在jump里执行button,a及seelct的绑定。会执行内部函数c,render的参数为空,即非第一次调用。
* render会调用用户回调,并再执行jump,此时jump的第二个参数为空。执行select,a,button的事件绑定及在skip函数里执行input的keyup事件绑定。
* 结束
*
* 模拟点击页码3
* 此时初次render已经结束。
* 点击页码3发生,即执行了a上绑定的click事件。
* 此时获取到页码3。
* 判断页码是否小于1大于总页码,不是,赋值给配置对象的curr,执行render,不传参数。
* this赋值给n。
* 配置对象赋值给i。
* 获取到type值为undefined,假设配置中写的是字符串。
* 生成view。
* 将view结果赋值给指定id元素。
* 判断是否设置了用户回调。
* 是,执行回调。此时render传入参数为空,即假。回调中如果设置了if(!first){}则会执行。
* 当前系统中会重新渲染table。
* 获取当前page容器元素。因为点击过后,执行了用户回调,而用户回调中再次调用了laypage.render,所以index会增1。
* 执行jump函数,传入此容器元素。
* 此时jump的第二个参数为假,因此在这一步就执行了button,select及a元素的事件绑定。
* 然后hash值赋值。
* 执行skip,为input绑定keyup事件。
* keyup事件中检测输入是否为上下左右键以及非数字,则input中值自动过滤掉这些字符,如果按下enter,则执行jump。
* 因为传入第二个参数为真,因此会先执行render,因为在keyup中可能输入的数字合法,必须要重新render。
* 结束。
*/
});

猜你喜欢

转载自www.cnblogs.com/jiangtian/p/laypage-explanation.html