前言
近几年根本都是开发SPA
利用,敌人找我帮忙做一个简略的后盾治理的模块,是传统的ASP.NET
WEB
页面,不过我这次还是写独立的前端界面的,只是会基于他们零碎应用的框架去开发(jq+bootstrap
)。
工作
- 列表页(搜寻、表格展现、分页)
- 表单提交页(新增/编辑)
技术框架
- jQuery
- bootstrap.js(v3)
- art-template
- wdate
- ...
例子:https://blog.csdn.net/weixin_...
开发笔记
原我的项目用的是v3
版本的bootstrap
表格
原我的项目中表格有用bootstrapTable
插件(性能看着挺齐全),因为其官网例子很多加载不进去(控制台报错),本人对它不相熟,且工作工夫紧放心用了前面要扩大不不便,我就没用它的。
表格我是申请数据后,间接用art-template模版引擎去渲染,简略的示例界面如下:
界面:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>art-Templat例子</title> <script src="./lib/art-template/template-web.js"></script> <style> table { border-collapse: collapse; border-spacing: 0; } table .th { background-color: #f5f5f5; font-size: 12px; font-weight: bold; } table tr { border-top: 1px solid #dfdfdf; } table tr:last-child { border-bottom: 1px solid #dfdfdf; } table tr td { padding: 4px 6px; font-size: 12px; } </style></head><body> <!--列表--> <table class="table"> <tbody id="table-tbody"> </tbody> </table> <!--列表内容模版--> <script id="tpl-table-tbody" type="text/html"> <tr class="th"> <td>ID</td> <td>订单号</td> <td>收货人</td> <td>手机号</td> <td>状态</td> <td>创建人</td> <td>创立工夫</td> </tr> {{each list}} <tr> <td>{{$value.id}}</td> <td>{{$value.orderNo}}</td> <td>{{$value.receiver}}</td> <td>{{$value.phone}}</td> <td>{{$value.status}}</td> <td>{{$value.creator}}</td> <td>{{$value.createTime}}</td> </tr> {{/each}} </script></body></html>
对应JS:
var html = template('tpl-table-tbody', { list: [{ id: 'XK001', orderNo: 'ORD202205180001', receiver: '张三', phone: '13512341234', status: '待发货', creator: '管理员', createTime: '2022-03-20 15:30:22' }, { id: 'XK002', orderNo: 'ORD202205180002', receiver: '张三', phone: '13512341234', status: '已实现', creator: '管理员', createTime: '2022-03-02 18:30:22' }, { id: 'XK003', orderNo: 'ORD202205180003', receiver: '张三', phone: '13512341234', status: '待收货', creator: '管理员', createTime: '2022-03-16 20:30:22' }] }); document.getElementById('table-tbody').innerHTML = html;
分页
因为表格是独自渲染了,就得再独自思考分页。
想要的成果:
我试了一下boostrapPagination
,成果和想要的差异有点大,如下图所示,页数很多时没有思考...
的展现,且首尾页时默认暗藏头尾按钮。
最初,本人基于网上的一个简略的例子重写了一个分页的小插件,成果如下。
demo页面:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>KPagination</title> <!-- 引入 zepto CDN 链接 --> <script src="https://cdnjs.gtimg.com/cdnjs/libs/zepto/1.1.4/zepto.js"></script> <style> body { font-size: 14px; } button { border-style: none; line-height: 30px; padding: 0 12px; margin-bottom: 20px; } </style></head><body> <button onclick="search()">搜寻</button> <div id="content"></div> <div id="pagination"></div></body><script src="./js/kPagination.js"></script></html>
页面JS:
function search() { getKPagination({ total: 185, totalPage: 18, curPage: 1, initCallback: function (page) { $('#content').html(`以后页码:${page}`); }, toPageCallback: function (page) { $('#content').html(`以后页码:${page}`); } }); }
KPagination.js
function getKPagination(opt) { const defaultOpt = { totalPage: 0, curPage: 1, total: 0, pageSize: 10, bootstrapCss: false //默认没引bootstarp款式。(此时会加上.pagination相干的款式) } const option = Object.assign({}, defaultOpt, opt); const kPagination = { curPage: option.curPage, totalPage: option.totalPage, total: option.total, pageSize: option.pageSize, toPageCallback: option.toPageCallback, initCallback: option.initCallback, pageEleID: 'pagination', init: false, getPaginationHtml: function (totalPage, curPage, total) { var paginationInfo = "<ul class=\"pagination pagination-sm\" >" + "<li><span class=\"label\">共" + total + "条记录</span></li>" + "<li><a data-i=" + (curPage - 1) + " data-disabled=\"" + ((curPage - 1) == 0 ? "true" : "false") + "\">«上一页</a></li>"; if (totalPage <= 10) { for (var i = 1; i <= totalPage; i++) { paginationInfo += "<li><a data-i=" + i + ">" + i + "</a></li>"; } } else { if (curPage <= 3) { for (var i = 1; i <= curPage + 2; i++) { paginationInfo += "<li><a data-i=" + i + ">" + i + "</a></li>"; } paginationInfo += "<li><span class=\"label\">...</span></li>"; paginationInfo += "<li><a data-i=" + totalPage + ">" + totalPage + "</a></li>"; } else if (curPage <= totalPage - 5) { paginationInfo += "<li><a data-i=" + 1 + ">" + 1 + "</a></li>"; paginationInfo += "<li><span class=\"label\">...</span></li>"; for (var i = curPage - 1; i <= curPage + 2; i++) { paginationInfo += "<li><a data-i=" + i + ">" + i + "</a></li>"; } paginationInfo += "<li><span class=\"label\">...</span></li>"; paginationInfo += "<li><a data-i=" + totalPage + ">" + totalPage + "</a></li>"; } else { paginationInfo += "<li><a data-i=" + 1 + ">" + 1 + "</a></li>"; paginationInfo += "<li><span class=\"label\">...</span></li>"; for (var i = curPage - 1; i <= totalPage; i++) { paginationInfo += "<li><a data-i=" + i + ">" + i + "</a></li>"; } } } paginationInfo += "<li><a data-i=" + (curPage + 1) + " data-disabled=\"" + (totalPage == 0 || curPage == totalPage ? "true" : "false") + "\">下一页»</a></li>"; return paginationInfo; }, refreshPagination: function (totalPage, curPage, total) { if (total > 0 && (curPage < 1 || curPage > totalPage)) { return; } var paginationInfo = this.getPaginationHtml(totalPage, curPage, total); document.getElementById(this.pageEleID).innerHTML = paginationInfo; $('.pagination li a').removeClass('current'); $('.pagination li a[data-i="' + curPage + '"]').addClass('current'); }, //分页条初始化 init: function () { this.addStyle(); var paginationInfo = this.getPaginationHtml(this.totalPage, this.curPage, this.total); document.getElementById(this.pageEleID).innerHTML = paginationInfo; $('.pagination li a[data-i="' + this.curPage + '"]').addClass('current'); //分页条点击切换查问 $('#' + this.pageEleID).on('click', '.pagination li a', (e) => { if (e.target.dataset['i'] == undefined) return false; if (e.target.dataset['disabled'] == 'true') return false; const page = parseInt(e.target.dataset['i']); this.toPageCallback && this.toPageCallback(page); this.refreshPagination(this.totalPage, page, this.total); return false; }); this.initCallback && this.initCallback(this.curPage); }, addStyle: function () { let style = ''; if (!this.bootstrapCss) { style += ` .pagination { display: inline-block; padding-left: 0; margin: 20px 0; border-radius: 4px } .pagination>li { display: inline } .pagination>li>a,.pagination>li>span { position: relative; float: left; padding: 6px 12px; margin-left: -1px; line-height: 1.428571429; text-decoration: none; background-color: #fff; border: 1px solid #ddd } .pagination>li:first-child>a,.pagination>li:first-child>span { margin-left: 0; border-bottom-left-radius: 4px; border-top-left-radius: 4px } .pagination>li:last-child>a,.pagination>li:last-child>span { border-top-right-radius: 4px; border-bottom-right-radius: 4px } .pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus { background-color: #eee } .pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus { z-index: 2; color: #fff; cursor: default; background-color: #488FCD; border-color: #488FCD } .pagination>.disabled>span,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus { color: #999; cursor: not-allowed; background-color: #fff; border-color: #ddd } .pagination-lg>li>a,.pagination-lg>li>span { padding: 10px 16px; font-size: 18px } .pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span { border-bottom-left-radius: 6px; border-top-left-radius: 6px } .pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span { border-top-right-radius: 6px; border-bottom-right-radius: 6px } .pagination-sm>li>a,.pagination-sm>li>span { padding: 5px 10px; font-size: 12px } .pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span { border-bottom-left-radius: 3px; border-top-left-radius: 3px } .pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span { border-top-right-radius: 3px; border-bottom-right-radius: 3px } `; } style += ` .pagination>li a:not([data-disabled="true"]):active{ color: #fff; background: #488FCD; border-color: #488FCD; } .pagination>li a:not([data-disabled="true"]).current { color: #fff; background: #488FCD; border-color: #488FCD; } .pagination a[data-disabled="true"] { color: #afafaf; cursor: not-allowed; } .pagination a[data-disabled="true"]:hover { color: #afafaf; cursor: not-allowed; } .pagination>li>a{ cursor:pointer; } .pagination>li>a, .pagination>li>span { color: #333; } .pagination>li .label,.pagination .label:hover{ cursor:initial; background-color: #ffffff; } `; const styleEle = document.createElement('style'); styleEle.type = 'text/css'; styleEle.innerText = style; var head = document.getElementsByTagName('head')[0] head.appendChild(styleEle); } } kPagination.init(); return kPagination;}
最初
良久没有这样比拟“原生态”的写前端了,哈哈哈,写写小工具小插件,还是感觉挺好玩的,这篇文章只是记录了:
- 页面渲染应用的是
art-template
模版引擎 - 简略封装了一个分页小插件的
KPagination.js
本次开发工作的笔记待续哦,前面还会补充其余性能的一些总结。
欢送大家戳戳留下足迹,欢送留言交换哦~
参考文献
- Bootstrap前端分页的实现(带省略号)