webdom

前言

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

实现原理

下拉刷新

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

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

 

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

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

上拉加载

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

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

 

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>移动端上拉刷新、下拉加载</title>
	<style type="text/css">
		html,body,header,div,main,p,span,ul,li{ margin: 0; padding: 0; }
		#refreshContainer li{ background-color: #eee; margin-bottom: 1px; padding: 20px 10px; }
		.refreshText{ position: absolute; width: 100%; line-height: 50px; text-align: center; left: 0; top: 0; }
		.bot_refreshText{ line-height: 50px; text-align: center; }
	</style>
</head>
<body>
<main>
	<p class="refreshText"></p>
	<ul id="refreshContainer">
		<li>111</li>
		<li>222</li>
		<li>333</li>
		<li>444</li>
		<li>555</li>
		<li>111</li>
		<li>222</li>
		<li>333</li>
		<li>444</li>
		<li>555</li>
		<li>111</li>
		<li>222</li>
		<li>333</li>
		<li>444</li>
		<li>555</li>
	</ul>
	<p class="bot_refreshText"></p>
</main>

<!--上拉刷新-->
<script type="text/javascript">
	(function(window) {
		var _element = document.getElementById(\'refreshContainer\'),
		  _refreshText = document.querySelector(\'.refreshText\'),
		  _startPos = 0,
		  _transitionHeight = 0;
		_element.addEventListener(\'touchstart\', function(e) {
			console.log(\'初始位置:\', e.touches[0].pageY);
			_startPos = e.touches[0].pageY;
			_element.style.position = \'relative\';
			_element.style.transition = \'transform 0s\';
		}, false);
		
		_element.addEventListener(\'touchmove\', function(e) {
			console.log(\'当前位置:\', e.touches[0].pageY);
			_transitionHeight = e.touches[0].pageY - _startPos;
			
			if (_transitionHeight > 0 && _transitionHeight < 60) {
				_refreshText.innerText = \'下拉刷新\';
				_element.style.transform = \'translateY(\'+_transitionHeight+\'px)\';
				if (_transitionHeight > 55) {
				  _refreshText.innerText = \'释放更新\';
				}
			}				
		}, false);
		_element.addEventListener(\'touchend\', function(e) {
			_element.style.transition = \'transform 0.5s ease 1s\';
			_element.style.transform = \'translateY(0px)\';
			_refreshText.innerText = \'更新中...\';
			// todo...
		}, false);
	})(window);
</script>

<!--下拉加载-->
<script type="text/javascript">
(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; 
    } 
    // 获取当前可视范围的高度 
    function getClientHeight() { 
	    var clientHeight = 0; 
	    if (document.body.clientHeight && document.documentElement.clientHeight) { 
	    	clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight); 
	    } 
	    else { 
	    	clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight); 
	    } 
	    return clientHeight; 
    }
    // 获取文档完整的高度 
    function getScrollHeight() { 
    	return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); 
    }
    var _text = document.querySelector(\'.bot_refreshText\'),
    _container = document.getElementById(\'refreshContainer\');
    var throttle = function(method, context){
		  clearTimeout(method.tId);
		  method.tId = setTimeout(function(){
		    method.call(context);
		  }, 300);
	}
    function fetchData() {
    	setTimeout(function() {
    		_container.insertAdjacentHTML(\'beforeend\', \'<li>new add...</li>\');
    	}, 1000);
    }
    window.onscroll = function() {
      	if (getScrollTop() + getClientHeight() == getScrollHeight()) {
      		_text.innerText = \'加载中...\';
      		throttle(fetchData);
      	}
    };
})(window);
</script>
</body>
</html>

  

 

小结

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

分类:

技术点:

相关文章:

  • 2021-09-26
  • 2021-08-12
  • 2021-06-06
  • 2021-12-11
  • 2021-12-09
  • 2021-11-22
  • 2021-12-09
  • 2021-12-09
猜你喜欢
  • 2021-12-09
  • 2021-12-09
  • 2021-12-09
  • 2021-11-22
  • 2021-12-09
  • 2021-11-22
  • 2021-05-20
  • 2021-10-30
相关资源
相似解决方案