这是手机端常见的一个功能,可能很多人都是用框架或者插件实现。
这里,我试着用原生js实现。
这样能更明白原理与底层实现
首先,布局,模拟初始数据
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Document</title><style>body {margin: 0;}html,body {height: 100%;}header,footer {width: 100%;height: 40px;position: absolute;left: 0;text-align: center;line-height: 40px;background: #999999;color: #ffffff;z-index: 999;}header {top: 0;}footer {bottom: 0;}ul {display: block;width: 100%;position: absolute;top: 40px;bottom: 40px;overflow: auto;list-style: none;padding: 0;margin: 0;}ul>li {width: 100%;height: 40px;line-height: 40px;text-indent: 20px;border-bottom: 1px solid #666666;background: #ffffff;color: #333333;}/* 下拉刷新的时候做 */#loading{width: 100%;height: 40px;line-height: 40px;text-align: center;color: #333333;transition: all 0.5s;position: absolute;z-index: 1;color: #ffffff;background: orange;top: 0;}</style></head><body><header>我是头部</header><section id="con"><div id="loading">加载中......</div><ul id="list"></ul></section><div id="loadEnd">已加载全部数据</div><footer>我是尾部</footer></body><script><script>//获取数据var list = document.getElementById("list");function getData() {var html = '';for (var i = 0; i < 20; i++) {html += '<li>我是第' + (i + 1) + '个li</li>';}list.innerHTML = html;}//初始加载函数window.onload = () => {//初始请求数据getData();}</script></script></html>
会得到这样一个网页,头部底部固定,中间部分可滑动
接下来,我们来监听ul的滚动事件
list.addEventListener("scroll", function () {//这里可以获取到ul距离屏幕顶部的距离,每次滚动都会刷新console.log(this.scrollTop);})
来做一个分析,接下来不要着急写代码
看到这个图,我们就知道要做什么了
//ul的高度 不变的 定死的let listH = list.clientHeight;//所有li总高度let contentH = this.childNodes.length * 41;//差值let diffValue = contentH - listH;//距离视窗还有50的时候,开始触发;if (this.scrollTop + 50 >= diffValue) {console.log('该加载了...')getData();}
上滑加载完美实现,当我滑到快到最后一个li的时候,触发获取数据的方法
我们再添加一个节流阀,不让它无限加载。
function getData() {var html = '';for (var i = 0; i < 20; i++) {html += '<li>我是第' + (i + 1) + '个li</li>';}var length = list.children.length;if (length === 0) {list.innerHTML = html;} else if(length > 0 && length < 100){//html是字符串 var newHtml = parseDom(html);//后面插入元素insertAfter(newHtml, list.children[length - 1]);}else if(length === 100){console.log("已经到底了,别拉了");}}
这里有两个非常重要的方法,都是原生js操作
1.字符串dom化
//字符串dom化function parseDom(arg) {var objEle = document.createElement("div");objEle.innerHTML = arg;return [...objEle.childNodes];};
2.在已有元素后面插入元素
//在已有元素后面插入元素function insertAfter(newElement, targetElement) {newElement.forEach(element => {//在后面插入元素 after:js新的dom api targetElement.after(element)});return}
下拉加载
通过判断ul的scrollTop值,当ul的scrollTop === 0的时候,触发
添加到监听滚动事件里,加一些样式操作即可
有些许粗糙,功能为主,见谅见谅
if(this.scrollTop === 0){list.style.top = "80px";loading.style.top = "40px";//刷新数据setTimeout(()=>{loading.style.top = "0";list.style.top = "40px";},1000)}
那么完整代码就是
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Document</title><style>body {margin: 0;}html,body {height: 100%;}header,footer {width: 100%;height: 40px;position: absolute;left: 0;text-align: center;line-height: 40px;background: #999999;color: #ffffff;z-index: 999;}header {top: 0;}footer {bottom: 0;}ul {display: block;width: 100%;position: absolute;top: 40px;bottom: 40px;overflow: auto;list-style: none;padding: 0;margin: 0;}ul>li {width: 100%;height: 40px;line-height: 40px;text-indent: 20px;border-bottom: 1px solid #666666;background: #ffffff;color: #333333;}/* 下拉刷新的时候做 */#loading,#loadEnd{width: 100%;height: 40px;line-height: 40px;text-align: center;color: #333333;transition: all 0.5s;position: absolute;z-index: 1;color: #ffffff;}#loading{background: orange;top: 0;}#loadEnd{background: green;bottom: 0;}</style></head><body><header>我是头部</header><section id="con"><div id="loading">加载中......</div><ul id="list"></ul></section><div id="loadEnd">已加载全部数据</div><footer>我是尾部</footer><script>//获取数据var list = document.getElementById("list");var loading = document.getElementById("loading");var loadEnd = document.getElementById("loadEnd");function getData() {var html = '';for (var i = 0; i < 20; i++) {html += '<li>我是第' + (i + 1) + '个li</li>';}var length = list.children.length;if (length === 0) {list.innerHTML = html;} else if(length > 0 && length < 100){//html是字符串 var newHtml = parseDom(html);//后面插入元素insertAfter(newHtml, list.children[length - 1]);}else if(length === 100){console.log("已经到底了,别拉了");list.style.bottom = "80px";loadEnd.style.bottom = "40px";//加个定时器模拟接口请求结束 隐藏掉此条//或者可以插入一条元素 }}//字符串dom化function parseDom(arg) {var objEle = document.createElement("div");objEle.innerHTML = arg;return [...objEle.childNodes];};//在已有元素后面插入元素function insertAfter(newElement, targetElement) {newElement.forEach(element => {//在后面插入元素 js 新的dom apitargetElement.after(element)});return}//初始加载函数window.onload = () => {//初始请求数据getData();list.addEventListener("scroll", function () {//ul的高度 不变的 定死的let listH = list.clientHeight;//所有li总高度let contentH = this.childNodes.length * 41;//下拉刷新if(this.scrollTop === 0){list.style.top = "80px";loading.style.top = "40px";//刷新数据setTimeout(()=>{loading.style.top = "0";list.style.top = "40px";},1000)}//距离let diffValue = contentH - listH;//ul离顶部的距离//距离视窗还有50的时候,开始触发;if (this.scrollTop + 50 >= diffValue) {console.log('该加载了...')getData();}})}</script></body></html>
此篇文章为作者原创
如需转载 请注明出处