原生js實現簡潔的返回頂部組件

来源:http://www.cnblogs.com/lyzg/archive/2016/03/15/5281690.html
-Advertisement-
Play Games

本文內容相當簡單,所以沒有發佈到博客園首頁,如果你不幸看到,那隻能是我這篇文章的榮幸,謝謝你的大駕光臨~


本文內容相當簡單,所以沒有發佈到博客園首頁,如果你不幸看到,那隻能是我這篇文章的榮幸,謝謝你的大駕光臨~(本博客返回頂部的功能就使用的是這個組件)

返回頂部組件是一種極其常見的網頁功能,需求簡單:頁面滾動一定距離後,顯示返回頂部的按鈕,點擊該按鈕可以將滾動條滾回至頁面開始的位置。實現思路也很容易,只要改變document.documentElement.scrollTop或document.body.scrollTop的值即可。本文拋棄所有加速減速的酷炫效果,回歸軟體的本質,提供一個最簡潔的實現,只追求實用性,不追求所謂的用戶體驗,效果如下(代碼下載):

demo

由於思路跟代碼都很簡單,所以就直接貼出實現細節了:

var BackTop = function (domE,distance) {
    if (!domE) return;
    var _onscroll = window.onscroll,
        _onclick = domE.onclick;

    window.onscroll = throttle(function(){
        typeof _onscroll === 'function' && _onscroll.apply(this, arguments);
        toggleDomE();
    },100);
    domE.onclick = function(){
        typeof _onclick === 'function' && _onclick.apply(this, arguments);
        document.documentElement.scrollTop = 0;
        document.body.scrollTop = 0;
    };

    function toggleDomE(){
        domE.style.display = (document.documentElement.scrollTop || document.body.scrollTop) > (distance || 500) ? 'block' : 'none';
    }

    function throttle(func, wait) {
        var timer = null;
        return function () {
            var self = this, args = arguments;
            if (timer) clearTimeout(timer);
            timer = setTimeout(function () {
                return typeof func === 'function' && func.apply(self, args);
            }, wait);
        }
    }
};

調用方式:

<script>
    new BackTop(document.getElementById('backTop'))
</script>

之所以寫這篇博客,弄這麼個簡單的東西,有兩個方面的原因:

1)這段時間一直在手寫一些常見的簡單組件,這算是一個簡單中更簡單的一個,為了讓這系列的博客更加完整,所以把這個組件補充了進來;

2)我想表達自己在工作過程中的一個觀點:就是不要過渡用用戶體驗來裝飾你的軟體或者說產品,用戶體驗這個東西說白了就是兩個詞,一個是好印象,第二個就是好玩,但這並不是產品開發運營的最終目的,你把東西做的再漂亮,產品的核心價值和服務做的不夠的話,就算把返回頂部這種功能做成超級無敵的火箭也是徒勞無功的。做前端開發,得鍛煉點控制產品經理瞎提用戶體驗功能的度,以這個組件來說,我認為做加速或減速效果都是多餘的,既增加開發時間,又耽誤用戶使用的時間,拋棄自己心中那點對技術玩弄的固執,可以讓自己的工作做的更加完美。

最後,還是非常感謝你把它看完:)


補充於2016-03-16:

感謝普通男孩在評論中指出的問題:由於我提供的實現在註冊事件回調的時候用的onscroll和onclick的方式,雖然在組件內部會記錄這兩個事件之前可能註冊的回調,併在註冊組件的回調時,會先調用之前的回調,但是還存在另外一種情況:別人可能使用了這個組件,並且在這個組件之後也用onscroll或onclick給同一個對象註冊事件,如果沒把之前的回調調用一下,就會導致組件內部的回調被它後定義的回調覆蓋,導致組件失效。如果用addEventListener來註冊事件就不會有這個問題,因為它是可針對同一個事件註冊多個回調的,並且不存在覆蓋的問題,所以在此提供另外一個改良版的實現(對應代碼中的backTop2.js和index2.html):

var BackTop = function(domE, distance) {
    if (!domE) return;

    var AddListener = function(domE, type, fn) {
        if (typeof domE.addEventListener === 'function') {
            AddListener = function(domE, type, fn) {
                domE.addEventListener(type, fn, false);
            };
        } else if (typeof el.attachEvent === 'function') {
            AddListener = function(domE, type, fn) {
                domE.attachEvent('on' + type, fn);
            };
        } else {
            AddListener = function(domE, type, fn) {
                var old = el['on' + type];        
                el['on' + type] = function(){
                    typeof old === 'function' && old.apply(this, arguments);
                    typeof fn === 'function' && fn.apply(this, arguments);
                };
            };
        }
        AddListener(domE, type, fn);
    }

    AddListener(window, 'scroll', throttle(function() {
        toggleDomE();
    }, 100));

    AddListener(domE, 'click', function() {
        document.documentElement.scrollTop = 0;
        document.body.scrollTop = 0;
    })

    function toggleDomE() {
        domE.style.display = (document.documentElement.scrollTop || document.body.scrollTop) > (distance || 500) ? 'block' : 'none';
    }

    function throttle(func, wait) {
        var timer = null;
        return function() {
            var self = this,
                args = arguments;
            if (timer) clearTimeout(timer);
            timer = setTimeout(function() {
                return typeof func === 'function' && func.apply(self, args);
            }, wait);
        }
    }
};

註:以上代碼中的AddListener以及throttle的實現均可抽出來,作為單獨的工具函數使用,這樣組件會看起來更簡潔。這裡是為了組件的完整性,才把她們放在一塊。throttle是函數節流的簡單實現。在下一篇文章中有更詳細地關於該函數作用的介紹:利用getBoundingClientRect方法實現簡潔的sticky組件


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

-Advertisement-
Play Games
更多相關文章
  • CSS命名規範 一.文件命名規範 全局樣式:global.css;框架佈局:layout.css;字體樣式:font.css;鏈接樣式:link.css;列印樣式:print.css; 二.常用類/ID命名規範 頁 眉:header內 容:content容 器:container頁 腳:footer
  • 第一次打開一個頁面時,讓載入好的圖片先隱藏,然後再執行動畫fadeIn。 這裡的load事件:當所有子元素已經被完全載入完成時,load事件被髮送到這個元素
  • (1)、工廠模式:封裝一個函數createPerson,這個函數可以創造一個人對象,包含三個屬性和一個方法,然後利用這個函數分別創建了2個對象p1,p2. 工廠模式下解決了創建多個相似對象的問題,但是卻沒有解決對象識別問題(不知道這個對象的類型是數組或函數或正則等)alert(p1 instance
  • border-radius瀏覽器相容性: IE9+、Firefox 4+、Chrome、Safari 5+ 以及 Opera 支持 border-radius 屬性。 <style>.box { position:relative; width: 99px; height: 99px; paddin
  • 前面提到 ES5 對象屬性描述符,這篇看看對象的擴展、密封和凍結。 阻止對象擴展,讓一個對象變的不可擴展,也就是永遠不能再添加新的屬性 ES3 是沒有辦法阻止對象擴展的,定義對象後可以給對象添加任意屬性,如 ES5 的 Object.preventExtensions 則可以阻止給對象添加新屬性 如
  • 重現代碼 以上網頁代碼,在 IE10/11 中輸出如下 可以看到IE10/11克隆時竟然把值賦給了value,這是一個的bug。 其它瀏覽器輸出的均是空字元串。 判斷是否有該bug的函數提取如下
  • Atitit. atiJavaExConverter4js 新的特性 1.1. V1新特性1 1.2. V2 新特性1 2. Keyword1 3. Catch1 4. Convert n Throw ex2 5. --atiex2 Java ex convert Catch 不同的ex Try c
  • Atitit hre框架v5 新特性 HREv5 1. V5新特性 apiurl2="/wrmiServlet";1 2. V1 新特性1 3. V2 新特性 添加php版1 4. V3 新特性 callback_checkJavaEx(data);1 5. V4 新特性1 基礎實現 <script
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...