原生js實現(xiàn)下拉刷新和上拉加載更多
本文實例為大家分享了js實現(xiàn)下拉刷新和上拉加載更多的具體代碼,供大家參考,具體內(nèi)容如下
1.下拉刷新
由于原生js太久不用了,這里列一下此處涉及到的前置知識點:
移動端觸屏事件: touchstart(手指按下的一瞬間),touchmove(手指在屏幕上移動時),touchend(手指松開時)
手指在頁面上的坐標: pageX,pageY
寫之前首先要懂原理,下拉刷新的本質(zhì)就是用戶在頁面頂部進行上拉動作時拉到一定的距離觸發(fā)數(shù)據(jù)刷新.
大概需要做的幾個點:
1.在手指按下時(touchstart)記錄手指的按下位置
2.在手指下滑時(touchmove)計算手指的坐標離手指按下時初始位置的差值得出下滑的距離,讓容器順應手指下滑的方向移動(translateY)對應差值的距離,對應的給一個允許用戶下滑的最大距離,避免頁面下拉過長.
3.在手指松開時(touchend)判斷下滑的差值是否達到預期的值來進行對應的刷新數(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盒子,下拉時才顯示出來 */
? ? ? ? ? ? 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;// 下拉距離的差值
? ? // 手指按下時
? ? container.addEventListener('touchstart', function (e) {
? ? ? ? // 在回彈后的下一次下拉按下時重置loading文本
? ? ? ? span.textContent = '下拉刷新';
? ? ? ? // 記錄開始位置
? ? ? ? startPosition = e.touches[0].pageY;
? ? })
? ? // 手指移動時
? ? container.addEventListener('touchmove', function (e) {
? ? ? ? // 計算下拉差值
? ? ? ? const currentPosition = e.touches[0].pageY;
? ? ? ? // 計算下拉后離開始位置的差值
? ? ? ? distance = currentPosition - startPosition;
? ? ? ? // 如果下拉差值達到,則提示可以松手了 這個達到的具體值這里是取的下拉出來的區(qū)域高度
? ? ? ? if (distance > 100) {// 案例以100為臨界值,超過了100的距離就提示釋放刷新
? ? ? ? ? ? span.textContent = '釋放刷新';
? ? ? ? }
? ? ? ? // 限制下滑的最大值為120,超過就不再下滑
? ? ? ? if (distance < 120) {
? ? ? ? ? ? // 容器的這個下滑是瞬時的 取消過渡效果
? ? ? ? ? ? this.style.transition = 'transform 0s';
? ? ? ? ? ? this.style.transform = `translateY(${distance}px)`
? ? ? ? }
? ? })
? ? // 手指松開時
? ? container.addEventListener('touchend', function (e) {
? ? ? ? // 回彈的動作可以給個1s的過渡效果
? ? ? ? this.style.transition = 'transform 1s';
? ? ? ? // 如果下拉差值并沒有達到 則直接回彈
? ? ? ? if (distance > 0 && distance < 100) {
? ? ? ? ? ? this.style.transform = `translateY(0px)`
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (distance > 100) {
? ? ? ? ? ? // 下拉差值達到了就顯示刷新中,并暫時定格在這個位置
? ? ? ? ? ? this.style.transform = `translateY(100px)`;
? ? ? ? ? ? span.textContent = '刷新中';
? ? ? ? ? ? // 等數(shù)據(jù)回來后顯示刷新成功1s然后再回彈 到這里本次整個下拉執(zhí)行完畢
? ? ? ? ? ? setTimeout(() => {// setTimeout模擬異步請求 真實開發(fā)這里是一個promise請求
? ? ? ? ? ? ? ? span.textContent = '刷新成功';
? ? ? ? ? ? ? ? // 這個setTimeout讓刷新成功顯示一秒后再回彈
? ? ? ? ? ? ? ? setTimeout(() => {
? ? ? ? ? ? ? ? ? ? this.style.transform = `translateY(0px)`
? ? ? ? ? ? ? ? }, 1000)
? ? ? ? ? ? }, 2000);
? ? ? ? }
? ? ? ? // 一次下拉結(jié)束后重置差值
? ? ? ? distance = 0;
? ? })
</script>
?
</html>效果如圖所示:

2.上拉加載
前置js知識點: 三個dom屬性
*clientHeight:不包含邊框的元素可視區(qū)高度
*scrollTop:元素滾動時卷上去的距離
*scrollHeight: 元素實際高度,包含卷上去的高度
知道了上述三個屬性后,于是就有了一個公式:
clientHeight + scrollTop <= scrollHeight - 觸底的指定距離
然后就是上拉加載的原理:
通過監(jiān)聽元素的滾動事件(scroll)判斷元素是否滾動到了距離底部指定距離時觸發(fā)加載數(shù)據(jù)
知道了原理和三者之間的關系后,我們就知道只需要判斷這個公式即可知道滾動條有沒有進入觸底距離,話不多說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) {
? ? ? ? // 當元素的可視高度+滾入的距離>=元素真實高度-觸底距離時,觸發(fā)加載更多
? ? ? ? if ((this.clientHeight + this.scrollTop) >= this.scrollHeight - 50) {
? ? ? ? ? ? setTimeout(() => {
? ? ? ? ? ? ? ? // 這里是一個異步加載數(shù)據(jù)的操作
? ? ? ? ? ? ? ? console.log('加載更多')
? ? ? ? ? ? }, 1000);
? ? ? ? }
? ? }, 700))
</script>
?
</html>效果如圖:

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
JavaScript中的淺拷貝和深拷貝原理與實現(xiàn)淺析
這篇文章主要介紹了JavaScript中的淺拷貝和深拷貝原理與實現(xiàn),JavaScript 中的淺拷貝和深拷貝指的是在復制對象(包括對象、數(shù)組等)時,是否只復制對象的引用地址或者在復制時創(chuàng)建一個新的對象2023-04-04
javascript 動態(tài)加載 css 方法總結(jié)
有時候我們在設計網(wǎng)頁的時候想動態(tài)的加載css文件,并不是將css文件寫死在頁面中,這時就可以使用下面方法.2009-07-07
Web componentd組件內(nèi)部事件回調(diào)及痛點剖析
這篇文章主要為大家介紹了Web componentd組件內(nèi)部事件回調(diào)示例及其痛點的剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2021-11-11

