国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

IScroll中當內容不足時(shí)下拉刷新的示例分析

發(fā)布時(shí)間:2021-07-27 11:48 來(lái)源:億速云 閱讀:0 作者:小新 欄目: web開(kāi)發(fā)

小編給大家分享一下IScroll中當內容不足時(shí)下拉刷新的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

大致的例子是這樣的:

<style>
 * {
 margin: 0;
 padding: 0;
 }
 html,body,.container {
 width: 100%;
 height: 100%;
 }
 .container>ul>li {
 padding: 15px 20px;
 text-align: center;
 border-bottom: 1px solid #ccc;
 }
</style>

<div id="container" class="container">
 <ul class="scroller">
 <li>item1</li>
 <li>item2</li>
 <li>item3</li>
 <li>item4</li>
 <li>item5</li>
 </ul>
</div>

<script src="https://.bootcss.com/iScroll/5.2.0/iscroll.min.js"></script>
<script>
 var myScroll = null;
 function onLoad() {
 myScroll = new IScroll('container');
 }
 window.addEventListener('DOMContentLoaded', onLoad, false);
</script>

那么,既然超過(guò)一屏是可以刷新的,那我們就來(lái)逛逛代碼吧。在github上搜索iscroll,打開(kāi)第一個(gè),找到src下面的core.js。

1. 思路

首先既然要下拉,肯定會(huì )觸發(fā)touchstart、touchmove以及touchend事件。搜索touchmove,很好,在_initEvents中的注冊了這個(gè)事件。

_initEvents: function (remove) {
 // ...
 // 這里省略若干代碼

 if ( utils.hasTouch && !this.options.disableTouch ) {
  eventType(this.wrapper, 'touchstart', this);
  eventType(target, 'touchmove', this);
  eventType(target, 'touchcancel', this);
  eventType(target, 'touchend', this);
 }

 // ...
},

好吧,看到這里的時(shí)候,我表示懵了一下逼,這不就是個(gè)綁定事件么?this又是一個(gè)什么鬼,然后我去查了一下文檔,發(fā)現了這么一個(gè)東西。文檔地址

target.addEventListener(type, listener[, options]);
target.addEventListener(type, listener[, useCapture]);
target.addEventListener(type, listener[, useCapture, wantsUntrusted ]); 
// 
// Gecko/Mozilla only

listener

當所監聽(tīng)的事件類(lèi)型觸發(fā)時(shí),會(huì )接收到一個(gè)事件通知(實(shí)現了 Event 接口的對象)對象。listener 必須是一個(gè)實(shí)現了 EventListener 接口的對象,或者是一個(gè)函數

木有看錯,listener是一個(gè)對象或者是一個(gè)函數。前提是這個(gè)對象實(shí)現了EventListener接口。我們接著(zhù)往下看,發(fā)現了這么一個(gè)例子。

var Something = function(element) {
 // |this| is a newly created object
 this.name = 'Something Good';
 this.handleEvent = function(event) {
 console.log(this.name); 
 // 'Something Good', as this is bound to newly created object
 switch(event.type) {
  case 'click':
  // some code here...
  break;
  case 'dblclick':
  // some code here...
  break;
 }
 };

 // Note that the listeners in this case are |this|, not this.handleEvent
 element.addEventListener('click', this, false);
 element.addEventListener('dblclick', this, false);

 // You can properly remove the listeners
 element.removeEventListener('click', this, false);
 element.removeEventListener('dblclick', this, false);
}
var s = new Something(document.body);

然后在去IScroll的源碼去找,發(fā)現了同樣的實(shí)現方式。在default文件夾中有一個(gè)handleEvent.js。

好了,這個(gè)梗先告一段落。還是繼續看源碼。在handleEvent.js中,有這么一段東西。

handleEvent: function (e) {
 switch ( e.type ) {
  case 'touchstart':
  case 'pointerdown':
  case 'MSPointerDown':
  case 'mousedown':
  this._start(e);
  break;
  case 'touchmove':
  case 'pointermove':
  case 'MSPointerMove':
  case 'mousemove':
  this._move(e);
  break;
  case 'touchend':
  case 'pointerup':
  case 'MSPointerUp':
  case 'mouseup':
  case 'touchcancel':
  case 'pointercancel':
  case 'MSPointerCancel':
  case 'mousecancel':
  this._end(e);
  break;
  // ...
 }
 }
};

發(fā)現在start/move/end分別調用了內部方法_start/_move/_end方法。去看看這三個(gè)方法,看其中可能會(huì )引起不會(huì )滑動(dòng)的點(diǎn)。

在_start方法中,看到這樣的幾行代碼,會(huì )不會(huì )是直接返回了呢?分析分析:

if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) {
 return;
}

// ...

var point = e.touches ? e.touches[0] : e,
 pos;

this.initiated = utils.eventType[e.type];
this.moved = false;
initiated屬性在最開(kāi)始肯定是沒(méi)有的,而enabled默認是true,所以在最開(kāi)始執行這個(gè)方法的時(shí)候是不會(huì )返回的,而是會(huì )給initiated這個(gè)屬性設置當前的eventType值,這個(gè)值會(huì )在_move方法中用到。重點(diǎn)來(lái)看看_move方法。

if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
 return;
}

首先來(lái)進(jìn)行類(lèi)型判斷,因為在_start方法中已經(jīng)定義了這個(gè)值,所以這里也不會(huì )返回。接著(zhù)往下看:

if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
 return;
}

【實(shí)際上是兩次click事件的模擬】如果兩次滑動(dòng)的時(shí)間大于了300ms,并且只要一個(gè)方向上的位移少于10像素,那么也是會(huì )返回的。那么會(huì )不會(huì )呢,打個(gè)斷點(diǎn)測試一下就知道了。這里就不貼圖了,實(shí)際中的測試結果是,每一次移動(dòng)肯定是在300ms以?xún)鹊?,這里之所以判斷300ms,主要是click事件執行會(huì )有一個(gè)300ms的延遲。而每一次移動(dòng),由于手指的觸點(diǎn)比較大,還是會(huì )大于10像素的,即使兩次不大于10像素,也是不影響的。所以這點(diǎn)不會(huì )返回。那么繼續接著(zhù)看:

// If you are scrolling in one direction lock the other
if ( !this.directionLocked && !this.options.freeScroll ) {
 if ( absDistX > absDistY + this.options.directionLockThreshold ) {
 this.directionLocked = 'h'; // lock horizontally
 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
 this.directionLocked = 'v'; // lock vertically
 } else {
 this.directionLocked = 'n'; // no lock
 }
}

if ( this.directionLocked == 'h' ) {
 if ( this.options.eventPassthrough == 'vertical' ) {
 e.preventDefault();
 } else if ( this.options.eventPassthrough == 'horizontal' ) {
 this.initiated = false;
 return;
 }

 deltaY = 0;
} else if ( this.directionLocked == 'v' ) {
 if ( this.options.eventPassthrough == 'horizontal' ) {
 e.preventDefault();
 } else if ( this.options.eventPassthrough == 'vertical' ) {
 this.initiated = false;
 return;
 }

 deltaX = 0;
}

第一個(gè)條件判斷只要是定義了這次滑動(dòng)的方向是什么。h表示水平方向,v表示豎直方向。我們是要向下滑動(dòng),所以我們關(guān)注的是豎直方向??吹诙€(gè)條件判斷,如果是豎直方向,那么將水平方向的deltaX值變?yōu)?。這樣做的目的是保持絕對的豎直方向。因為移動(dòng)實(shí)際還是根據元素的位移值來(lái)的。當probe的版本為2以下的時(shí)候,是根據css3的transform屬性來(lái)移動(dòng)位移的,為3版本的時(shí)候是根據決定對位來(lái)移動(dòng)的。所以這里只要不把我們的deltaY置為0就說(shuō)明木有什么問(wèn)題。繼續往下看代碼:

deltaX = this.hasHorizontalScroll ? deltaX : 0;
deltaY = this.hasVerticalScroll ? deltaY : 0;

newX = this.x + deltaX;
newY = this.y + deltaY;
// ...

// 這里是移動(dòng)
this._translate(newX, newY);

測試中發(fā)現,這個(gè)hasVerticalScroll一直是false,那么deltaY一直就是0,也就是移動(dòng)了也白移動(dòng)。找到問(wèn)題原因。那么,這個(gè)hasVerticalScroll是從哪里來(lái)的?全局找呀找,在refresh中找到這樣幾行代碼:

this.wrapperWidth = this.wrapper.clientWidth;
this.wrapperHeight = this.wrapper.clientHeight;

var rect = utils.getRect(this.scroller);
/* REPLACE START: refresh */

this.scrollerWidth = rect.width;
this.scrollerHeight = rect.height;

this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
this.maxScrollY = this.wrapperHeight - this.scrollerHeight;

/* REPLACE END: refresh */

this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;

refresh方法會(huì )在IScroll實(shí)例化的時(shí)候調用一次。粗略一看,scrollY內置為true,所以只有maxScrollY會(huì )大于0。往上看。this.wrapperHeight - this.scrollerHeight肯定是大于0的呀,這就是問(wèn)題所在。

那么看看我們最開(kāi)始代碼,這里的wrapperHeight為文檔高度,scrollerHeight為內容高度,所以wrapperHeight高度始終大于scrollHeight。但是,手機端頁(yè)面夾雜的列表,一般都有頭部、底部,而中間部分一般都會(huì )采用padding的形式來(lái)使得列表在全局滾動(dòng),這樣就不需要每次都要特定地計算列表的高度。

2. 解決方案

針對以上問(wèn)題,只要我們能夠使內部的滾動(dòng)部分高度大于容器高度,那么就能觸發(fā)滾動(dòng)。

2.1 粗略做法

可以設置一個(gè)min-height屬性為900px(900只是一個(gè)示例,只要夠大就可以),這樣就可以保證可以滑動(dòng)。

2.2 精準做法

計算當前的容器高度,然后比容器高度多一個(gè)像素即可。

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系站長(cháng)郵箱:ts@56dr.com進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

成全动漫视频在线观看完整版| www国产精品内射| 性深夜免费福利视频| 人妻丝袜乱经典系列| 狠狠人妻久久久久久综合蜜桃| 亚洲国产日韩A在线播放|