上拉加载和下拉刷新的原理

H5下拉刷新和上拉加载实现原理浅析

前言

在移动端H5网页中,下拉刷新和上拉加载更多数据的交互方式出现频率很高,开源社区也有很多类似的解决方案,如iscroll,pulltorefresh.js库等。下面是对这两种常见交互基本实现原理的阐述。

实现原理

下拉刷新

实现下拉刷新主要分为三步:

  • 监听原生touchstart事件,记录其初始位置的值,e.touches[0].pageY
  • 监听原生touchmove事件,记录并计算当前滑动的位置值与初始位置值的差值,大于0表示向下拉动,并借助CSS3的translateY属性使元素跟随手势向下滑动对应的差值,同时也应设置一个允许滑动的最大值;
  • 监听原生touchend事件,若此时元素滑动达到最大值,则触发callback,同时将translateY重设为0,元素回到初始位置。

示例。查看链接:下拉刷新demo(PC浏览器需调成手机模拟器模式查看)

复制代码
<main>
    <p class="refreshText"></p>
    <ul id="refreshContainer">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
        <li>555</li>
        ...
    </ul>
</main>
复制代码
复制代码
(function(window) {
    var _element = document.getElementById('refreshContainer'),
      _refreshText = document.querySelector('.refreshText'),
      _startPos = 0,
      _transitionHeight = 0;
_element.addEventListener(</span>'touchstart', <span style="color: #0000ff;">function</span><span style="color: #000000;">(e) {
    console.log(</span>'初始位置:', e.touches[0<span style="color: #000000;">].pageY);
    _startPos </span>= e.touches[0<span style="color: #000000;">].pageY;
    _element.style.position </span>= 'relative'<span style="color: #000000;">;
    _element.style.transition </span>= 'transform 0s'<span style="color: #000000;">;
}, </span><span style="color: #0000ff;">false</span><span style="color: #000000;">);

_element.addEventListener(</span>'touchmove', <span style="color: #0000ff;">function</span><span style="color: #000000;">(e) {
    console.log(</span>'当前位置:', e.touches[0<span style="color: #000000;">].pageY);
    _transitionHeight </span>= e.touches[0].pageY -<span style="color: #000000;"> _startPos;

    </span><span style="color: #0000ff;">if</span> (_transitionHeight &gt; 0 &amp;&amp; _transitionHeight &lt; 60<span style="color: #000000;">) {
        _refreshText.innerText </span>= '下拉刷新'<span style="color: #000000;">;
        _element.style.transform </span>= 'translateY('+_transitionHeight+'px)'<span style="color: #000000;">;

        </span><span style="color: #0000ff;">if</span> (_transitionHeight &gt; 55<span style="color: #000000;">) {
          _refreshText.innerText </span>= '释放更新'<span style="color: #000000;">;
        }
    }                
}, </span><span style="color: #0000ff;">false</span><span style="color: #000000;">);

_element.addEventListener(</span>'touchend', <span style="color: #0000ff;">function</span><span style="color: #000000;">(e) {
    _element.style.transition </span>= 'transform 0.5s ease 1s'<span style="color: #000000;">;
    _element.style.transform </span>= 'translateY(0px)'<span style="color: #000000;">;
    _refreshText.innerText </span>= '更新中...'<span style="color: #000000;">;

    </span><span style="color: #008000;">//</span><span style="color: #008000;"> todo...</span>
}, false ); })(window);
复制代码

在下拉到松手的过程中,经历了三个状态:

  • 当前手势滑动位置与初始位置差值大于零时,提示正在进行下拉刷新操作;
  • 下拉到一定值时,显示松手释放后的操作提示;
  • 下拉到达设定最大值松手时,执行回调,提示正在进行更新操作。
上拉加载

上拉加载更多数据是在页面滚动时触发的动作,一般是页面滚动到底部时触发,也可以选择在滚动到一定位置的时候触发。

以滚动到页面底部为例。实现原理是分别获得当前滚动条的scrollTop值、当前可视范围的高度值clientHeight以及文档的总高度scrollHeight。当scrollTopclientHeight的值之和大于等于scrollHeight时,触发callback

示例。查看链接:上拉加载demo

复制代码
<main>
    <ul id="refreshContainer">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
        <li>555</li>
        ...
    </ul>
    <p class="refreshText"></p>
</main>
复制代码
复制代码
(function(window) {
    // 获取当前滚动条的位置 
    function getScrollTop() { 
        var scrollTop = 0; 
        if (document.documentElement && document.documentElement.scrollTop) { 
            scrollTop = document.documentElement.scrollTop; 
        } else if (document.body) { 
            scrollTop = document.body.scrollTop; 
        } 
        return scrollTop; 
    } 
</span><span style="color: #008000;">//</span><span style="color: #008000;"> 获取当前可视范围的高度 </span>
<span style="color: #0000ff;">function</span><span style="color: #000000;"> getClientHeight() { 
    </span><span style="color: #0000ff;">var</span> clientHeight = 0<span style="color: #000000;">; 
    </span><span style="color: #0000ff;">if</span> (document.body.clientHeight &amp;&amp;<span style="color: #000000;"> document.documentElement.clientHeight) { 
        clientHeight </span>=<span style="color: #000000;"> Math.min(document.body.clientHeight, document.documentElement.clientHeight); 
    } 
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> { 
        clientHeight </span>=<span style="color: #000000;"> Math.max(document.body.clientHeight, document.documentElement.clientHeight); 
    } 
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> clientHeight; 
} 

</span><span style="color: #008000;">//</span><span style="color: #008000;"> 获取文档完整的高度 </span>
<span style="color: #0000ff;">function</span><span style="color: #000000;"> getScrollHeight() { 
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); 
}

</span><span style="color: #0000ff;">var</span> _text = document.querySelector('.refreshText'<span style="color: #000000;">),
  _container </span>= document.getElementById('refreshContainer'<span style="color: #000000;">);

</span><span style="color: #008000;">//</span><span style="color: #008000;"> 节流函数</span>
<span style="color: #0000ff;">var</span> throttle = <span style="color: #0000ff;">function</span><span style="color: #000000;">(method, context){
  clearTimeout(method.tId);
  method.tId </span>= setTimeout(<span style="color: #0000ff;">function</span><span style="color: #000000;">(){
    method.call(context);
  }, </span>300<span style="color: #000000;">);
}

</span><span style="color: #0000ff;">function</span><span style="color: #000000;"> fetchData() {
    setTimeout(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() {
        _container.insertAdjacentHTML(</span>'beforeend', '&lt;li&gt;new add...&lt;/li&gt;'<span style="color: #000000;">);
    }, </span>1000<span style="color: #000000;">);
}

window.onscroll </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">() {
  </span><span style="color: #0000ff;">if</span> (getScrollTop() + getClientHeight() ==<span style="color: #000000;"> getScrollHeight()) {
      _text.innerText </span>= '加载中...'<span style="color: #000000;">;
      throttle(fetchData);
  }
};

})(window);

复制代码

页面绑定onscroll事件时加入了节流函数,其作用就是忽略滚动条300毫秒内的连续多次触发。

小结

上拉刷新的实现主要依靠的是touch事件的三个阶段,以及借助CSS3动画效果;下拉加载主要依靠页面的onscroll事件,需要注意的是页面滚动时可能要考虑函数节流。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值