all-of-javascript icon indicating copy to clipboard operation
all-of-javascript copied to clipboard

h5上拉加载下拉刷新

Open cbbfcd opened this issue 7 years ago • 0 comments

参考:

原理剖析

offsetHeight、clientHeight、scrollTop等

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>pull</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html, body, header, div, main, p, span, ul, li {
      margin: 0;
      padding: 0;
    }
    .wrapper li {
      list-style: none;
      padding: 20px 10px;
      background-color: #eee;
      margin-bottom: 1px; 
    }
    .refresh {
      position: absolute;
      width: 100%;
      line-height: 50px;
      text-align: center;
      left: 0;
      top: 0;
    }
    .more {
      line-height: 50px;
      text-align: center;
    }
  </style>
</head>
<body>
  <main>
    <p class="refresh"></p>
    <ul class="wrapper">
      <li>a</li>
      <li>b</li>
      <li>c</li>
      <li>d</li>
      <li>e</li>
      <li>f</li>
      <li>g</li>
      <li>h</li>
      <li>i</li>
      <li>j</li>
      <li>k</li>
      <li>l</li>
      <li>m</li>
    </ul>
    <p class="more"></p>
  </main>
</body>
<script>
  (function(window){
    // 下拉刷新
    var refreshTarget = document.querySelector('.wrapper');
    var refreshTip = document.querySelector('.refresh');
    var moreTip = document.querySelector('.more');
    var addEventListener = refreshTarget.addEventListener;
    var removeEventListener = refreshTarget.removeEventListener;
    var style = refreshTarget.style;
    var location = window.location;
    var start = 0;
    var transformHeight = 0;
    var offset = 60;
    var boby = document.body;
    var dbody = document.documentElement;

    // 节流函数
    function throttle(fn, wait, options){
      var timeout, context, args, previous = 0;
      if(!options) options = {};

      var later = function(){
        previous = options.leading === false ? 0 : +new Date();
        timeout = null;
        fn.apply(context, args);
        if(!timeout) context = args = null;
      }

      var throttled = function(){
        var now = +new Date();
        if(options.leading === false && !previous) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if(remaining <= 0 || remaining > wait){
          if(timeout){
            clearTimeout(timeout);
            timeout = null;
          }
          previous = now;
          fn.apply(context, args);
          if(!timeout) context = args = null;
        }else if(!timeout && options.trailing !== false){
          timeout = setTimeout(later, remaining);
        }
      }

      return throttled
    }

    var handleTouchStart = function(e){
      var ele = e.touches[0] || e.changedTouches[0];
      start = ele.pageY;
      style.position = 'relative';
      style.transition = 'transform 0s';
    }

    var handleTouchMove = function(e){
      var ele = e.touches[0] || e.changedTouches[0];
      transformHeight = ele.pageY - start;
      if(transformHeight > 0 && transformHeight < offset){
        refreshTip.innerText = '下拉刷新';
        style.transform = 'translateY(' + transformHeight + 'px)';
        if(transformHeight > 55){
          refreshTip.innerText = '松开刷新';
        }
      }
    }

    var handleTouchEnd = function(e){
      refreshTip.innerText = '更新中...';
      var timeout = setTimeout(function(){
        clearTimeout(timeout);
        timeout = null;
        style.transition = 'transform 0.5s ease';
        style.transform = 'translateY(0px)';
        location.reload();
      }, 2000)
    }

    addEventListener('touchstart', handleTouchStart, false);
    addEventListener('touchmove', handleTouchMove, false);
    addEventListener('touchend', handleTouchEnd, false);

    var removeListeners = function(){
      removeEventListener('touchstart', handleTouchStart);
      removeEventListener('touchmove', handleTouchMove);
      removeEventListener('touchend', handleTouchEnd);
    }

    // 上拉加载更多
    var fetch = function(){
      setTimeout(function(){
        refreshTarget.insertAdjacentHTML('beforeend', '<li>新增加的...</li>');
      }, 1000)
    }

    var getClientHeight = function(){
      var clientHeight = 0, bodyClientHeight = boby.clientHeight, dbodyClientHeight = dbody.clientHeight;
      if(bodyClientHeight && dbodyClientHeight){
        clientHeight = Math.min(bodyClientHeight, dbodyClientHeight);
      }else{
        clientHeight = Math.max(bodyClientHeight, dbodyClientHeight);
      }
      return clientHeight;
    }

    var getScrollTop = function(){
      var scrollTop = 0;
      if(dbody && dbody.scrollTop){ // if DTD
        scrollTop = dbody.scrollTop;
      }else if(boby){
        scrollTop = boby.scrollTop;
      }
      return scrollTop;
    }

    var getScrollHeight = function(){
      return Math.max(document.body.scrollHeight, dbody.scrollHeight);
    }

    window.onscroll = throttle(function(){
      // 到底部了
      if(getClientHeight() + getScrollTop() >= getScrollHeight()){
        moreTip.innerText = '加载中...'
        fetch();
      }
    }, 1000, {leading: false, trailing: true});
  })(window)
</script>
</html>

cbbfcd avatar Nov 08 '18 12:11 cbbfcd