移動端效果之ScrollList

来源:http://www.cnblogs.com/rynxiao/archive/2017/11/17/7852122.html
-Advertisement-
Play Games

寫在前面 列表一直是展示數據的一個重要方式,在手機端的列表展示又和PC端展示不同,畢竟手機端主要靠滑。之前手機端之前一直使用的 ,但是 本身其實有很多相容性 ,想改動一下需求也很不容易,可以看我之前寫的這一文章 "IScroll那些事——內容不足時下拉刷新" (這裡並不是說 不好,裡面對手機、瀏覽器 ...


寫在前面

列表一直是展示數據的一個重要方式,在手機端的列表展示又和PC端展示不同,畢竟手機端主要靠滑。之前手機端之前一直使用的IScroll,但是IScroll本身其實有很多相容性BUG,想改動一下需求也很不容易,可以看我之前寫的這一文章IScroll那些事——內容不足時下拉刷新(這裡並不是說IScroll不好,裡面對手機、瀏覽器相容性都做了大量的處理,只是當遇到bug時或者想改一下需求時不時特別方便,畢竟是一個這麼大的庫)。因此也一直想瞭解一下這類列表的實現原理,萬一真到時候可以自己寫一個,這樣自己維護自己的代碼也可以更加得心應手。

下麵主要是閱讀了餓了麽UI組件庫mint-ui然後編寫出來的效果圖:

LoadMore

代碼請看這裡:github

移動端效果之swiper

移動端效果之picker

移動端效果之cellSwiper

移動端效果之IndexList

1 核心解析

1.1 整體思路圖

silu

1.2 HTML結構

<div class="page-loadmore-wrapper">
    <div id='loadMore' class="loadmore">
        <div id="loadMoreContent" class="loadmore-content">
            <!-- 這裡是頂部狀態生成的地方 -->
            <ul class="page-loadmore-list" id="loadMoreList"></ul>
            <!-- 這裡是底部狀態生成的地方 -->
        </div>
    </div>
</div>

這裡有一點需要註意,滑動內容部分需要一個設置為overflow:scroll的容器,如果不設置,就會一直向上找,直到最後返回window,這點在下麵的代碼可以體現

/**
 * 獲取滾動容器
 * @param  DOM element 
 * @return 
 */
getScrollEventTarget: function(element) {
    var currentNode = element;
    while (currentNode && currentNode.tagName !== 'HTML' &&
         currentNode.tagName !== 'BODY' && currentNode.nodeType === 1) {
        var overflowY = document.defaultView.getComputedStyle(currentNode).overflowY;
        if (overflowY === 'scroll' || overflowY === 'auto') {
            return currentNode;
        }
        currentNode = currentNode.parentNode;
    }
    return window;
}

1.3 滑動彈性與狀態變化

這兩點我們在touchmove事件中可以找到相應的代碼:

// 彈性滑動
// 這裡用手指滑動的位移除以比例繫數來得出內容應該滑動的位移
// 因此這裡的內容滑動的位移一定是會小於手指滑動的位移的,除非你將系列設置為小於1,那我就沒得話說了
// 於是就造成了一種滑動又滑不動的感覺
var distance = (_this.currentY - _this.startY) / _this.config.distanceIndex;

// 下移條件
// 1. 必須有刷新函數
// 2. 方向為向下
// 3. 初始的scrollTop為0
// 4. 狀態不為載入中
if (typeof _this.config.topMethod === 'function' && _this.direction === 'down' &&
    _this.getScrollTop(_this.scrollEventTarget) === 0 && _this.topStatus !== 'loading') {
    event.preventDefault();
    event.stopPropagation();

    if (_this.config.maxDistance > 0) {
        _this.translate = distance <= _this.config.maxDistance ? distance - _this.startScrollTop : _this.translate;
    } else {
        _this.translate = distance - _this.startScrollTop;
    }

    if (_this.translate < 0) {
        _this.translate = 0;
    }

    // 這裡是滑動中(touchmove)時應該判斷的
    // 如果滑動的位移操作了我們設置的值就置為pull
    // 同時更新狀態,改變內容的transform
    // 同理可以在向上拉動的時候找到相應的代碼,這裡不作累述
    _this.topStatus = _this.translate >= _this.config.topDistance ? 'drop' : 'pull';

    Event.trigger('topStatus', _this.topStatus);
    Event.trigger('translate', _this.translate);
}

// 在向上滑動的過程中,還需要時刻檢測是否已經滑倒最下麵了
// 如果沒有滑倒最下麵,則正常滑動,否則,載入新的數據
if (_this.direction === 'up') {
    _this.bottomReached = _this.bottomReached || _this.checkBottomReached();
}

1.4 載入數據

當狀態在loading的時候,就是載入數據的時候,而只有當滑動停止之後,狀態才需要置為loading,因此載入數據的代碼需要在touchend中執行,具體看下麵代碼註釋:

// 這裡分析向下刷新數據時候的代碼
// 向上部分的類似,可以自行去瞭解
if (_this.direction === 'down' && _this.getScrollTop(_this.scrollEventTarget) === 0 && _this.translate > 0) {
    // 這裡觸發topDropped為true是為了給內容部分加上動畫
    Event.trigger('topDropped', true);

    // 判斷當前是否已經拉倒了足夠的位移,只有狀態為drop的時候放手才會載入數據
    if (_this.topStatus === 'drop') {
        // 重置狀態為loading,改變位移
        Event.trigger('topStatus', 'loading');
        // 向下移動50px像素是為了展示出loading的文字
        Event.trigger('translate', 50);

        // 載入數據
        _this.config.topMethod(function() {
            var args = [].slice.call(arguments);
            _this.onTopLoaded.apply(_this, args);
        });
    } else {
        // 如果向下拉動狀態仍為pull,說明拉動的距離很小
        Event.trigger('translate', 0);
        Event.trigger('topStatus', 'pull');
    }
}

1.5 上拉載入數據完成之後

這裡與下拉刷新有一點小小的不同,這裡貼一下代碼:

onBottomLoaded: function(list, isAllLoaded) {
    Event.trigger('bottomStatus', 'pull');
    Event.trigger('bottomDropped', false);
    Event.trigger('data', list);

    // 這裡給scrollEventTarget設置了scrollTop為50是為了防止跳動
    if (this.scrollEventTarget === window) {
        document.body.scrollTop += 50;
    } else {
        this.scrollEventTarget.scrollTop += 50;
    }

    Event.trigger('translate', 0);
    this.bottomAllLoaded = isAllLoaded;
}

1.6 關於數據初始化填充

在數據內容不足一屏時,如果設置了autoFill欄位為true的話,會自動調用一遍bottomMethod來填充數據

fillContainer: function() {
    var _this = this;

    // 如果自動填充
    if (this.config.autoFill) {
        // 根據滾動容器來判斷當前數據是否已經填充滿容器
        if (this.scrollEventTarget === window) {
            this.containerFilled = this.$el.getBoundingClientRect().bottom >=
                document.documentElement.getBoundingClientRect().bottom;
        } else {
            this.containerFilled = this.$el.getBoundingClientRect().bottom >=
            this.scrollEventTarget.getBoundingClientRect().bottom;
        }

        // 如果數據沒有填充滿容器,則載入數據
        if (!this.containerFilled) {
            // 這裡算是一點小遺憾,為了在自動載入loading的時候,顯示出狀態
            // 將內容部分位移了-50px,這就是為什麼在自動載入的時候會出現一個跳動的過程
            Event.trigger('bottomStatus', 'loading');
            Event.trigger('translate', -50);
            var data = this.config.bottomMethod(function(list) {
                Event.trigger('data', list);
                Event.trigger('bottomStatus', 'pull');
                Event.trigger('translate', 0);
            });
        }
    }
},

2 總結

最開始會認為這樣的效果實現起來會比較複雜(不過實際上確實也寫了快500到600行代碼了

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 網站開發開發大致分為前端和後端,前端主要負責實現視覺和交互效果,以及與伺服器通信,完成業務邏輯。其核心價值在於對用戶體驗的追求。如果你現在是零基礎學員,大致可以按如下思路學習系統學習: 基礎部分 1、HTML + CSS 這部分學習,可以模仿一些網站做些頁面。在實踐中積累了一些經驗後,可以系統的讀一 ...
  • 一、現象 表單提交時需要處理輸入框的回車事件,一般的原生input標簽可以用@keyup.enter="onSubmit"(tips:onSubmit為定義的方法) 二、解決 1、@keyup.enter="onSubmit" 改寫為 @keyup.enter.native="onSubmit" , ...
  • 一、簡介 Selectize是一個可擴展的基於jQuery 的自定義下拉框的UI控制項。它對展示標簽、聯繫人列表、國家選擇器等比較有用。它的大小在~ 7kb(gzip壓縮)左右。提供一個可靠且體驗良好的乾凈和強大的API。 功能介紹: 選項可查詢和排序; 使用箭頭鍵←和→在1️⃣選中選項之間移動; 對 ...
  • 一、函數的概念 日常生活中,我們要完成一件事,總是習慣先有一個計劃,後期按照計劃,一步一步執行,則能夠完成,並且達到一定效果實現一定的功能。在編程的世界里,“功能”可稱呼為“函數”,因此“函數”即一段實現了某種功能的代碼,並且可以供其他代碼調用。 在JavaScript中,函數是由事件驅動的,或者當 ...
  • 學了一段時間的HTML、CSS和JS後,給大家做一款漂亮的不像實力派的HTML時鐘,先看圖:涉及到的知識點有: CSS3動畫、DOM操作、定時器、圓點坐標的計算(好多人是不是已經還給自己的老師了~) 接下來,我們用5步來製作它 step1、準備HTML 首先,我們需要準備HTML結構,背景、表盤、指 ...
  • 上傳頭都是比較複雜的一件事,最近幫朋友找了一款插件給大家分享一下。 ps:這個可以根據你的設計稿自由發揮 可以寫成各種樣式,不會再有固定插件的樣式; 演示地址:http://durenlong.gitee.io/uploading 碼雲地址:https://gitee.com/durenlong/u ...
  • 這裡主要是模擬小米官網中的首頁的內容模塊實現的主要動態效果 佈局:採用了bootstrap框架進行佈局,及其其中的字體圖標 html: <!-- 內容 --> <div class="content_box"> <h2>內容</h2> <div class="row content_list"> < ...
  • 整理JavaScript方面的一些技巧,比較實用的函數,常見功能實現方法,僅作參考 變數轉換 但是轉換日期(new Date(myVar))和正則表達式(new RegExp(myVar))必須使用構造函數,創建正則表達式的時候要使用/pattern/flags這樣的簡化形式。 取整同時轉換成數值型 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...