某日,在公司写一个简单的活动页面,活动见链接 ,这个页面业务叫简单,核心就是一个分页内容,活动很快就搞定了,然后呢,就整理分页功能,写成一个插件。
嗯~~~说弄就弄。
首先呢,先将页面分成两个区域:内容展示区和控件按钮(分页,上下页,跳转页等)展示区
<div class="page-wrapper"> <div class="page-content"> 内容区域 </div> <div class="control-wrapper"> 分页按钮区域 </div> </div>
页面结构是弄好了,那么下面就要开始写JS了。
之前呢,公司也有类似的分页功能的功能函数,其采用的做法是:
1. 请求接口获取所有的数据
2. 将所有数据分页渲染到几个div中,类似的方式
3. 然后用 tab 页的形式,控制 div 显示隐藏
这样的话,如果数据比较少还是ok的,但如果数据比较多的话,会出现几个问题,
1. 接口请求时间问题
2. 数据渲染时间问题(采用的 dom 渲染方式,这样页面需要较长的时间才能加载显示出来,用户体验就很差)
解决办法呢?
一、接口改成分页请求
1. 前端负责写一个模板页面,然后将分页模板交给后端;前端只需负责分页按钮的状态,给按钮加链接即可。(整个页面会刷新)
2. 后端把总页数给前端,前端根据页码请求不同页面的内容
二、优化渲染时间
1. 把接口所有的数据请求出来
2. 将所有数据分页,保存在一个对象中,如: { page: 1, content: .... }
3. 分页渲染各个页面的内容
在听到大佬的指点后,感觉自己的代码还是有问题的,故分享下思路和整体代码。后续优化完后,在对文章修改。
1、根据请求的数据,对数据进行分页保存。
2、根据需求,在分页控制器内添加相应的html。
3、渲染分页按钮和内容。
当前完整代码如下。
var Paganation = function (el, options) { /* * baseUrl string 跳转链接(*) * curPage number 当前页(*) 从1开始 * totalPage number 总页数(*) * arrow boolean 是否有上下页 * showLen number 显示的按钮个数 * pageDetail boolean 是否显示具体的页码 * isTail boolean 首尾页 * isShowInfo boolean 是否显示页数详情 * ellipsisClass string 省略号类名 * prefix string 按钮类名前缀 */ this.el = el; let baseOptions = Object.assign({ baseUrl: null, curPage: 1, totalPage: 100, isArrow: true, showNum: 10, prefix: 'page-', disabledClass: 'page-disabled', isTail: true, pageDetail: true, isShowInfo: true, ellipsisClass: '' }, options); /* * prev string 上一页 * next string 下一页 * start string 首页 * end string 尾页 * page strign 具体的页码 * info string 页码详情 */ this.prevHTML = ''; this.nextHTML = ''; this.startHTML = ''; this.endHTML = ''; this.pageHTML = ''; this.infoHTML = ''; this._init(baseOptions); }; Paganation.prototype = { constructor: Paganation, _analysisOptions: function (options) { for (let k in options) { this[k] = options[k]; } }, _init: function (options) { this._analysisOptions(options); if (!this.baseUrl) { throw new Error(`must set baseUrl`); } if (!this.el) { throw new Error(`must set a page container`); }; this._render(); }, // set html _create: function () { this.curPage = +this.curPage; this.totalPage = +this.totalPage; if (this.curPage < 1) this.curPage = 1; if (this.curPage > this.totalPage) this.curPage = this.totalPage; if (this.isArrow) this._createArrow(); if (this.isTail) this._createTail(); if (this.isShowInfo) this._createInfo(); if (this.pageDetail) this._createPage(); }, // 上下页 _createArrow: function () { const disabledClass = this.disabledClass; const prevUrl = this.curPage == 1 ? 'javascript:void(0);' : this.baseUrl + (this.curPage - 1); const nextUrl = this.curPage == this.totalPage ? 'javascript:void(0);' : this.baseUrl + (+this.curPage + 1); const prevDisabled = this.curPage == 1 ? disabledClass : ''; const nextDisabled = this.curPage == this.totalPage ? disabledClass : ''; this.prevHTML = '<a class="' + this.prefix + 'item ' + prevDisabled + '" href="' + prevUrl + '">上一页</a>'; this.nextHTML = '<a class="' + this.prefix + 'item ' + nextDisabled + '" href="' + nextUrl + '">下一页</a>'; }, // 首尾页 _createTail: function () { const disabledClass = this.disabledClass; const startUrl = this.curPage == 1 ? 'javascript:void(0);' : this.baseUrl + 1; const endUrl = this.curPage == this.totalPage ? 'javascript:void(0);' : this.baseUrl + this.totalPage; const startDisabled = this.curPage == 1 ? disabledClass : ''; const endDisabled = this.curPage == this.totalPage ? disabledClass : ''; this.startHTML = '<a class="' + this.prefix + 'item ' + startDisabled + '" href="' + startUrl + '">首页</a>'; this.endHTML = '<a class="' + this.prefix + 'item ' + endDisabled + '" href="' + endUrl + '">尾页</a>'; }, // 页数详情 _createInfo: function () { this.infoHTML = '<span class="' + this.prefix + 'total">共<i>' + this.totalPage + '</i>页</span><span class="' + this.prefix + 'cur">当前第<i>' + this.curPage + '</i>页</span>' }, // 具体的页码 _createPage: function () { let str = ''; let self = this; let showNum = this.showNum; let totalPage = this.totalPage; let curPage = this.curPage; const prefix = this.prefix; const centerStr = '<span class="' + this.ellipsisClass + '">...</span>'; let urlFn = function (i) { return self.baseUrl + i; }; let htmlStr = function (i) { const endabled = self.curPage == i ? self.disabledClass : ''; return '<a class="' + prefix + 'item ' + endabled + '" href="' + urlFn(i) + '">' + i + '</a>'; }; if (showNum >= totalPage) { for (let i = 1; i <= totalPage; i++) { str += htmlStr(i) } } else { if (curPage < totalPage - showNum + 1) { //头部 for (let i = 0; i < showNum - 1; i++) { str += htmlStr(+curPage + i); } str += centerStr + htmlStr(totalPage); } else { // 尾部 for (let i = 1; i <= showNum; i++) { str += htmlStr(totalPage - showNum + i); } } } this.pageHTML = str; }, _goPage: function (i) { this.curPage = i; this._render(); }, _render: function () { this._create(); this.el.innerHTML = this.infoHTML + this.startHTML + this.prevHTML + this.pageHTML + this.nextHTML + this.endHTML; } }