原生js實(shí)現(xiàn)下拉刷新和上拉加載更多
本文實(shí)例為大家分享了js實(shí)現(xiàn)下拉刷新和上拉加載更多的具體代碼,供大家參考,具體內(nèi)容如下
1.下拉刷新
由于原生js太久不用了,這里列一下此處涉及到的前置知識點(diǎn):
移動端觸屏事件: touchstart(手指按下的一瞬間),touchmove(手指在屏幕上移動時(shí)),touchend(手指松開時(shí))
手指在頁面上的坐標(biāo): pageX,pageY
寫之前首先要懂原理,下拉刷新的本質(zhì)就是用戶在頁面頂部進(jìn)行上拉動作時(shí)拉到一定的距離觸發(fā)數(shù)據(jù)刷新.
大概需要做的幾個(gè)點(diǎn):
1.在手指按下時(shí)(touchstart)記錄手指的按下位置
2.在手指下滑時(shí)(touchmove)計(jì)算手指的坐標(biāo)離手指按下時(shí)初始位置的差值得出下滑的距離,讓容器順應(yīng)手指下滑的方向移動(translateY)對應(yīng)差值的距離,對應(yīng)的給一個(gè)允許用戶下滑的最大距離,避免頁面下拉過長.
3.在手指松開時(shí)(touchend)判斷下滑的差值是否達(dá)到預(yù)期的值來進(jìn)行對應(yīng)的刷新數(shù)據(jù)和回彈loading.
less word,show me the code...
<!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, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> ? ? <title>Document</title> ? ? <style type="text/css"> ? ? ? ? * { ? ? ? ? ? ? margin: 0; ? ? ? ? ? ? padding: 0; ? ? ? ? ? ? list-style: none; ? ? ? ? } ? ? ? ? ? .container { ? ? ? ? ? ? /* 容器原始位置向上移動60px,隱藏掉loading盒子,下拉時(shí)才顯示出來 */ ? ? ? ? ? ? position: relative; ? ? ? ? ? ? top: -100px; ? ? ? ? } ? ? ? ? ? .container .loading { ? ? ? ? ? ? text-align: center; ? ? ? ? ? ? height: 100px; ? ? ? ? ? ? line-height: 100px; ? ? ? ? } ? ? ? ? ? .container .list { ? ? ? ? ? ? border: 1px solid #666; ? ? ? ? } ? ? ? ? ? .container .list li { ? ? ? ? ? ? line-height: 80px; ? ? ? ? } ? ? ? ? ? .container .list li:nth-child(2n) { ? ? ? ? ? ? background-color: #ccc; ? ? ? ? } ? ? </style> </head> ? <body> ? ? <section class="container"> ? ? ? ? <section class="loading"> ? ? ? ? ? ? <span>下拉刷新</span> ? ? ? ? </section> ? ? ? ? <section class="list"> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? </section> ? ? </section> </body> <script type="text/javascript"> ? ? // 滾動容器 ? ? const container = document.querySelector('.container'); ? ? // loading文字容器 ? ? const span = container.querySelector('span'); ? ? let startPosition = 0;// 下拉的開始位置 ? ? let distance = 0;// 下拉距離的差值 ? ? // 手指按下時(shí) ? ? container.addEventListener('touchstart', function (e) { ? ? ? ? // 在回彈后的下一次下拉按下時(shí)重置loading文本 ? ? ? ? span.textContent = '下拉刷新'; ? ? ? ? // 記錄開始位置 ? ? ? ? startPosition = e.touches[0].pageY; ? ? }) ? ? // 手指移動時(shí) ? ? container.addEventListener('touchmove', function (e) { ? ? ? ? // 計(jì)算下拉差值 ? ? ? ? const currentPosition = e.touches[0].pageY; ? ? ? ? // 計(jì)算下拉后離開始位置的差值 ? ? ? ? distance = currentPosition - startPosition; ? ? ? ? // 如果下拉差值達(dá)到,則提示可以松手了 這個(gè)達(dá)到的具體值這里是取的下拉出來的區(qū)域高度 ? ? ? ? if (distance > 100) {// 案例以100為臨界值,超過了100的距離就提示釋放刷新 ? ? ? ? ? ? span.textContent = '釋放刷新'; ? ? ? ? } ? ? ? ? // 限制下滑的最大值為120,超過就不再下滑 ? ? ? ? if (distance < 120) { ? ? ? ? ? ? // 容器的這個(gè)下滑是瞬時(shí)的 取消過渡效果 ? ? ? ? ? ? this.style.transition = 'transform 0s'; ? ? ? ? ? ? this.style.transform = `translateY(${distance}px)` ? ? ? ? } ? ? }) ? ? // 手指松開時(shí) ? ? container.addEventListener('touchend', function (e) { ? ? ? ? // 回彈的動作可以給個(gè)1s的過渡效果 ? ? ? ? this.style.transition = 'transform 1s'; ? ? ? ? // 如果下拉差值并沒有達(dá)到 則直接回彈 ? ? ? ? if (distance > 0 && distance < 100) { ? ? ? ? ? ? this.style.transform = `translateY(0px)` ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? if (distance > 100) { ? ? ? ? ? ? // 下拉差值達(dá)到了就顯示刷新中,并暫時(shí)定格在這個(gè)位置 ? ? ? ? ? ? this.style.transform = `translateY(100px)`; ? ? ? ? ? ? span.textContent = '刷新中'; ? ? ? ? ? ? // 等數(shù)據(jù)回來后顯示刷新成功1s然后再回彈 到這里本次整個(gè)下拉執(zhí)行完畢 ? ? ? ? ? ? setTimeout(() => {// setTimeout模擬異步請求 真實(shí)開發(fā)這里是一個(gè)promise請求 ? ? ? ? ? ? ? ? span.textContent = '刷新成功'; ? ? ? ? ? ? ? ? // 這個(gè)setTimeout讓刷新成功顯示一秒后再回彈 ? ? ? ? ? ? ? ? setTimeout(() => { ? ? ? ? ? ? ? ? ? ? this.style.transform = `translateY(0px)` ? ? ? ? ? ? ? ? }, 1000) ? ? ? ? ? ? }, 2000); ? ? ? ? } ? ? ? ? // 一次下拉結(jié)束后重置差值 ? ? ? ? distance = 0; ? ? }) </script> ? </html>
效果如圖所示:
2.上拉加載
前置js知識點(diǎn): 三個(gè)dom屬性
*clientHeight:不包含邊框的元素可視區(qū)高度
*scrollTop:元素滾動時(shí)卷上去的距離
*scrollHeight: 元素實(shí)際高度,包含卷上去的高度
知道了上述三個(gè)屬性后,于是就有了一個(gè)公式:
clientHeight + scrollTop <= scrollHeight - 觸底的指定距離
然后就是上拉加載的原理:
通過監(jiān)聽元素的滾動事件(scroll)判斷元素是否滾動到了距離底部指定距離時(shí)觸發(fā)加載數(shù)據(jù)
知道了原理和三者之間的關(guān)系后,我們就知道只需要判斷這個(gè)公式即可知道滾動條有沒有進(jìn)入觸底距離,話不多說show code~
<!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, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> ? ? <title>Document</title> ? ? <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script> ? ? <style type="text/css"> ? ? ? ? * { ? ? ? ? ? ? margin: 0; ? ? ? ? ? ? padding: 0; ? ? ? ? ? ? list-style: none; ? ? ? ? } ? ? ? ? ? .container { ? ? ? ? ? ? height: 100vh; ? ? ? ? ? ? overflow-y: scroll; ? ? ? ? } ? ? ? ? ? .container .list { ? ? ? ? ? ? border: 1px solid #666; ? ? ? ? } ? ? ? ? ? .container .list li { ? ? ? ? ? ? line-height: 80px; ? ? ? ? } ? ? ? ? ? .container .list li:nth-child(2n) { ? ? ? ? ? ? background-color: #ccc; ? ? ? ? } ? ? </style> </head> ? <body> ? ? <section class="container"> ? ? ? ? <section class="list"> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? ? ? <li>我是內(nèi)容</li> ? ? ? ? </section> ? ? </section> </body> <script type="text/javascript" defer="defer"> ? ? // 滾動容器 ? ? const container = document.querySelector('.container'); ? ? // 監(jiān)聽滾動事件 ? ? container.addEventListener('scroll', _.debounce(function (e) { ? ? ? ? // 當(dāng)元素的可視高度+滾入的距離>=元素真實(shí)高度-觸底距離時(shí),觸發(fā)加載更多 ? ? ? ? if ((this.clientHeight + this.scrollTop) >= this.scrollHeight - 50) { ? ? ? ? ? ? setTimeout(() => { ? ? ? ? ? ? ? ? // 這里是一個(gè)異步加載數(shù)據(jù)的操作 ? ? ? ? ? ? ? ? console.log('加載更多') ? ? ? ? ? ? }, 1000); ? ? ? ? } ? ? }, 700)) </script> ? </html>
效果如圖:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript 文章截取部分無損html顯示實(shí)現(xiàn)代碼
近在做一些內(nèi)容搜索的工作,搜索出來的內(nèi)容為html格式,列表部分需要顯示每項(xiàng)內(nèi)容的一部分。2010-05-05JavaScript移除數(shù)組內(nèi)重復(fù)元素的方法
這篇文章主要介紹了JavaScript移除數(shù)組內(nèi)重復(fù)元素的方法,實(shí)例分析了javascript遍歷數(shù)組及刪除等操作的相關(guān)技巧,需要的朋友可以參考下2015-03-03跟我學(xué)習(xí)javascript的prototype使用注意事項(xiàng)
跟我學(xué)習(xí)javascript的prototype使用注意事項(xiàng),介紹了在使用prototype的幾點(diǎn)注意事項(xiàng),需要的朋友可以參考下2015-11-11