js实现跨平台滑动加载
一、原理讲解
1、首先,用一个有固定高度的div作为list,并将其overflow-y设置为auto或visible
2、当滑动到底部时,在list div底部插入加载效果元素,并向服务器请求数据,请求时发送请求的页数(当前页数+1)索引与搜索关键字。
3、服务器返回的数据可以是html、json、xml等数据,如果是html,则将其插入到list,如果是json或xml则生成html后插入到list。插入之后将当前页数+1,如果服务器返回的数据为空,则当前页数不变。不管请求是否成功,是否返回数据,都将加载效果元素从list中移除。
二、简单实现
本实现服务端用的是ASP.NET Core,滑动加载时返回的HTML。
1、先贴后台代码
1 public IActionResult SlidingLoading(string kw, int pageIndex = 1) 2 { 3 var list = new List<string>(); 4 for (int i = 1; i <= 10; i++) 5 { 6 list.Add($"第{(pageIndex - 1) * 10 + i}条数据"); 7 } 8 //ajax加载返回列表项 9 if (Request.Headers.ContainsKey("X-Requested-With")) 10 { 11 if(Request.Headers["X-Requested-With"] == "XMLHttpRequest") 12 { 13 return View("SlidingLoading.partial", list); 14 } 15 } 16 //否则返回主页 17 return View(list); 18 }
2、再贴JS代码
1 function SlidingLoading() { 2 var _this = this; 3 //当前搜索关键字,搜素后滑动加载时保持不变,除非重新搜索 4 var keyword = ""; 5 //layer弹出层索引 6 var layerIndex = 0; 7 //记录一个值,该值为当前是否在加载中,1:加载中,0不在加载中 8 var flagloading = 0; 9 //加载中效果元素 10 var $loading = $("<div>", { class: "loading" }).html("<i class=''></i><label>加载中...</label>"); 11 //空列表效果元素 12 var $empty = $("<div>", { class: "empty" }).html("<i class=''></i><label>暂无记录</label>"); 13 // 列表jquery对象 14 var $list; 15 //搜索框jquery对象 16 var $kw; 17 var defaults = { 18 url : "",//请求数据的url 19 pageIndex : 0,//初始列表页数 20 kwSelector : "#kw",//搜索框 21 itemSelector : ".item",//列表项 22 listSelector: ".list",//列表 23 btnSelector: "#btn-search",//搜索按钮 24 //生成 请求数据时发送给服务器的数据(默认返回JSON),其他请重写 25 //获取请求页数与搜索关键字 26 //bsearch,为true则将请求页数至为1,否则加1,重写时可根据此参数确定返回的页数 27 //覆盖此方法时应很小心,必须返回请求的页数 28 getJson: function (bsearch) { 29 if (bsearch) { 30 return { pageIndex: 1, kw: $kw.val() }; 31 } 32 else { 33 return { pageIndex: defaults.pageIndex + 1, kw: $kw.val() } 34 } 35 } 36 }; 37 38 //获取当前的页数 39 this.getPageIndex = function () { 40 return pageIndex; 41 } 42 //获取当前搜索关键字 43 this.getKeyword = function () { 44 return keyword; 45 } 46 //初始化 47 //options可覆盖defaults 48 this.init = function (options) { 49 $.extend(defaults, options); 50 $list = $(defaults.listSelector); 51 $kw = $(defaults.kwSelector); 52 //绑定滑动事件 53 $list.on("scroll", function () { 54 var height = this.clientHeight; 55 var top = this.scrollTop; 56 var totalHeight = this.scrollHeight; 57 if (top + height - totalHeight == 0) { 58 more(); 59 } 60 }); 61 //绑定搜索框事件enter事件 62 $kw.on("keypress", function (e) { 63 if (e.keyCode == 13) { 64 s(); 65 } 66 }); 67 //绑定搜索按钮 68 $(defaults.btnSelector).click(s); 69 } 70 //搜索 71 function s() { 72 //当前在加载中就返回 73 if (flagloading != 0) { 74 return; 75 } 76 flagloading = 1; 77 //显示搜索动画 78 layerIndex = layer.open({ type: 2 }); 79 keyword = $kw.val(); 80 $.ajax({ 81 url: defaults.url, 82 data: defaults.getJson(true), 83 type: "post", 84 beforeSend: function () { }, 85 success: function (data) { 86 //搜索成功后移除所有列表项 87 $list.children(defaults.itemSelector).remove(); 88 //如果返回的列表项不为空 89 if (data.trim()) { 90 $empty.remove(); 91 //假设返回的为html,则可以直接插入到list 92 $list.append(data); 93 //将页数至为1 94 defaults.pageIndex = 1; 95 } 96 else { 97 //列表为空,将空列表效果添加到list 98 $empty.appendTo($list); 99 defaults.pageIndex = 0; 100 } 101 }, 102 error: function () { },//页数不变,列表数据不清空 103 complete: function () { 104 //关闭搜索动画 105 layer.close(layerIndex); 106 //更改状态为非加载中 107 flagloading = 0; 108 } 109 }); 110 } 111 112 function more() { 113 //获取当前页数 114 var _pageIndex = defaults.pageIndex; 115 if (flagloading == 1) { 116 return; 117 } 118 $.ajax({ 119 url: defaults.url, 120 type: "post", 121 data: defaults.getJson(false), 122 beforeSend: function () { 123 $empty.remove(); 124 //将加载效果添加到列表 125 $loading.appendTo($list); 126 flagloading = 1; 127 }, 128 success: function (data) { 129 //返回数据不为空 130 if (data.trim()) { 131 //假设返回的是html 132 $list.append(data); 133 //将当前页数+1 134 defaults.pageIndex += 1; 135 } 136 //返回数据为空 137 else { 138 //当请页数为0 139 if (defaults.pageIndex == 0) { 140 //将空列表效果加入到list 141 if ($list.children(".empty").length == 0) { 142 $empty.appendTo($list); 143 } 144 } 145 } 146 }, 147 complete: function () { 148 //移除加载效果 149 $loading.remove(); 150 setTimeout(function () { flagloading = 0; }, 200); 151 } 152 }); 153 } 154 }
3、然后是示例
本实现有两个视图,一个是主视图,list定义在其中。一个是局部视图,用于快速生成列表项的HTML。
1 @using System.Collections.Generic 2 @model List<string> 3 @{ 4 Layout = null; 5 } 6 7 <!DOCTYPE html> 8 9 <html> 10 <head> 11 <meta name="viewport" content="width=device-width" /> 12 <title>SlidingLoading</title> 13 <link href="~/css/slidingloading.css?v=3" rel="stylesheet" /> 14 <style> 15 .title{ 16 text-align:center; 17 font-size:1.2rem; 18 19 } 20 .searh-wrapper{ 21 display:flex; 22 justify-content:center; 23 padding:1rem; 24 } 25 </style> 26 </head> 27 <body> 28 <div class="title"> 29 <label>轻量简易分页工具</label> 30 </div> 31 <div class="searh-wrapper"> 32 <input type="search" name="kw" id="kw" /><button id="btn-search">搜索</button> 33 </div> 34 <div class="list"> 35 @Html.Partial("SlidingLoading.partial", Model) 36 </div> 37 <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> 38 <script src="https://cdn.bootcss.com/layer/3.1.0/mobile/layer.js"></script> 39 <script src="~/js/slidingloading.js"></script> 40 <script> 41 var pager = new SlidingLoading(); 42 pager.init({ 43 pageIndex: 1,//当前显示到第几页 44 listSelector: ".list",//列表id或class 45 itemSelector: ".item",//列表项的class 46 btnSelector: "#btn-search",//搜索按钮 47 kwSelector:"#kw",//搜索关键字输入框 48 }); 49 </script> 50 </body> 51 </html>
1 @using System.Collections.Generic 2 @model List<string> 3 4 @foreach (var item in Model) 5 { 6 <div class="item"> 7 <label>@item</label> 8 </div> 9 }
1 *{ 2 padding:0; 3 margin:0; 4 box-sizing:border-box; 5 } 6 html,body{ 7 width:100%; 8 height:100%; 9 font-size:14px; 10 background-color:whitesmoke; 11 } 12 body{ 13 display:flex; 14 flex-direction:column; 15 align-items:stretch; 16 } 17 /*列表的高度必须固定,且overflow-y必须为auto*/ 18 .list{ 19 overflow-x:hidden; 20 overflow-y:auto; 21 position:relative;/*很重要,配合item的absolute*/ 22 padding-bottom:3rem; 23 flex:1; 24 } 25 /*item必须是list的直接子元素*/ 26 .list>.item{ 27 width:100%; 28 margin-top:1rem; 29 padding:2rem; 30 background-color:white; 31 } 32 /*加载效果,空列表效果*/ 33 .list > .loading, 34 .list > .empty { 35 display:flex; 36 align-items:center; 37 justify-content:center; 38 /*绝对定位很重要*/ 39 position: absolute; 40 left:0; 41 right:0; 42 height:3rem; 43 44 } 45 .list>.loading{ 46 /*使加载框显示再列表最下面*/ 47 margin-bottom:0; 48 }
效果图