移動端效果之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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...