一看就懂,js插件编写,以手机H5分页举例
巨大的建筑,总是由一木一石叠起来的,我们何妨做做这一木一石呢?我时常做些零碎事,就是为此。
这是对的,但是我没有说过这句话! —— 鲁迅
整理一下js插件的编写,这里以手机端H5分页举例。
即一共有1000条数据,每次只加载20条,当滑到底端的时候再默认加载20条,直到将所有数据加载完成。
封装性
将自己的代码隔开,使其他代码不会受到任何影响。
(function (win,$) {
})(window,$);
$是Jquery,window的作用是将自己写的插件暴露出来,让window可以直接调用.
组成部分
定义一个插件名,包括要传输的参数,即一个类的定义。
定义插件,也是要在这里进行参数传递。
/***
* 插件名,首字母大写,可以向对待类一样对待,如:new MobilePage()
* @param url 要请求的地址
* @param type get,post,put等
* @param data 要传输的数据.
* @param callcack success后要执行的函数.
*/
var MobilePage = function (options) {
this.url = options.url;
this.type = options.type;
this.data = options.data;
this.callback = options.callcack;
this.pageParams = {
//对应 sql中的 limit(0,3)
start:0,
length:3
};
//当次请求的数据长度,有可能=pageParams.length ,也有可能 < pagePaarams.length(最后一页)
this.dataLength = this.pageParams.length;
this.dataTotal;//记录一下数据的总长度
}
给插件增加方法
对插件添加方法,添加方法,要加到prototype中,这样相当于多个对象公用一套方法(跟java中的存储一样).
MobilePage.prototype = {
init:function () {
}
}
当然,更好的写法是一个方法一个方法的写,上面这种写法会将MobilePage的prototype中已有的方法覆盖掉.
MobilePage.prototype.init = function {
}
或者用JQuery的extend方法进行加载
MobilePage.prototype = $.extend(MobilePage.prototype,{
init:function () {
}
});
将插件的使用暴露出来.
一般一个页面只有一个分页,这时候只new一次,可以提供一个对象,自动new出来,并暴露给window.
win.MobilePage = MobilePage;
win.mobilePageUtil = {
request:function (url,type,data,callback) {
return new MobilePage(url,type,data,callback);
}
}
核心方法
请求方法
类似于$.ajax等.
request:function () {
var me = this;
me.data.pageParams = JSON.stringify(me.pageParams);
$.ajax({
type:me.type,
url: me.url,
data:me.data,
dataType: "json",
success: function (result) {
console.info(result);
if (result.code == 'SUCCESS') {
var data = result.data;
if (me.callback) {
me.callback(data);
}
//这个data应该是一个数组,求一下length
me.dataLength = data.length;
me.dataTotal = result.total;
}
}
});
}
将$.ajax封装一下,如果成功的话,则执行回调方法。并设置自己的一些属性,包括一共有多少数据,当前返回数据有多少条,便于分页的设置。
下一页方法
nextPage:function () {
this.pageParams.start += this.dataLength;
//调用请求方法.
if (this.pageParams.start < this.dataTotal) {
this.request();
} else {
console.info("我已经到底线了,没有数据可加载了")
}
},
修改start数值,判断是否加载已完成.
增加触发事件的方法
这里是用的window的scroll事件,来实现,这里有3个高度。
- contentH 内容的高度,也就是document的高度。
- viewH 屏幕的高度,也就是window的高度
-
scrollTop 滚动的高度,当滚动到最底下的时候,理论上 contentH == viewH + scrollTop
image.png
所以现在用 contentH == viewH + scrollTop 来判断是否滑到了最底部,假如滑到了,则触发事件,重新从服务器端请求数据.
init:function () {
var me = this;
//添加下拉触发的事件
$(win).scroll(function () {
var contentH = $(document).height();
var viewH = $(this).height();
var scrollTop = $(this).scrollTop();
console.info("contentH:" + contentH);
console.info("viewH:" + viewH);
console.info("scrollTop:" + scrollTop);
if (viewH + scrollTop == contentH) {
//拉到底了还拉.
console.info("已经拉到底了,你还拉");
//发起请求.
me.nextPage();
}
});
},
关于 var me = this;
因为this经常变换,用变量记录当时this的指向.
调用
mobilePageUtil.request({
url: api_host + "/question/mobile/study",
type: 'GET',
data: {questionType: 'CHOICE'},
callback: makeAddtionHtmls
});
由于在插件中已经将mobilePageUtil 通过 window.mobilePageUtil 暴露给了window,所以这里可以直接使用
makeAddtionHtmls为具体的方法,注意可以接受一个list的参数.
function makeAddtionHtmls(questionList) {
console.info(questionList);
}
全部代码展示
上面介绍的是思路,代码稍有冲突,代码以下面的为准.
/**
* 手机端分页,上拉加载,用scroll事件,嵌入到App中去.
* @author liuzhenning
* @version 0.0.1
* @since 0.0.1 2019/02/27
*/
//封装成一个分页插件,自己写,将自己的代码隔离开
(function (win,document,$) {
/***
* 插件名,首字母大写,可以向对待类一样对待,如:new MobilePage()
* @param url 要请求的地址
* @param type get,post,put等
* @param data 要传输的数据.
* @param callcack success后要执行的函数.
*/
var MobilePage = function (options) {
// var MobilePage = function (url,type,data,callcack) {
//仿照$.ajax的模式,传输对象,便于维护,方便增加属性
this.url = options.url;
this.type = options.type;
this.data = options.data;
this.callback = options.callback;
this.pageParams = {
start:0,
length:3
};
//当次请求的数据长度,有可能=pageParams.length ,也有可能 < pagePaarams.length(最后一页)
this.dataLength = this.pageParams.length;
this.dataTotal;//记录一下数据的总长度
//初始化
this.init();
//调一次加载数据,首页.
this.request();
}
//对插件添加方法,添加方法,要加到prototype中,这样相当于多个对象公用一套方法(跟java中的存储一样).
MobilePage.prototype = {
init:function () {
var me = this;
//添加下拉触发的事件
$(win).scroll(function () {
var contentH = $(document).height();
var viewH = $(this).height();
var scrollTop = $(this).scrollTop();
console.info("contentH:" + contentH);
console.info("viewH:" + viewH);
console.info("scrollTop:" + scrollTop);
if (viewH + scrollTop == contentH) {
//拉到底了还拉.
console.info("已经拉到底了,你还拉");
//发起请求.
me.nextPage();
}
});
},
nextPage:function () {
this.pageParams.start += this.dataLength;
//调用请求方法.
if (this.pageParams.start < this.dataTotal) {
this.request();
} else {
console.info("我已经到底线了,没有数据可加载了")
}
},
request:function () {
var me = this;
me.data.pageParams = JSON.stringify(me.pageParams);
$.ajax({
type:me.type,
url: me.url,
data:me.data,
dataType: "json",
success: function (result) {
console.info(result);
if (result.code == 'SUCCESS') {
var data = result.data;
if (me.callback) {
me.callback(data);
}
//这个data应该是一个数组,求一下length
me.dataLength = data.length;
me.dataTotal = result.total;
}
}
});
},
reset:function () {
this.pageParams.start = 0;
}
}
//一般一个页面只有一个分页,这时候只new一次,可以提供一个对象,自动new出来,并暴露给window.
win.MobilePage = MobilePage;
win.mobilePageUtil = {
//只request1次,之后的request,是靠事件触发的,也就是再request的时候,那参数直接置为默认了,无需reset.
request:function (options) {
return new MobilePage(options);
}
}
})(window,document,$);
其他
因为手机端,要考虑内存容量的问题,所以这里用jquery的话会有点大,小编这里使用的是zepto,效果一样的。