每日 30 秒 ⏱ 迴囬囘回到頂部

簡介

回到頁面頂部、兼容性、最佳寫法、滾動到任意處javascript

你們一塊兒被捕吧 中剛寫了:css

在平常開發中咱們每每會從用戶那得到各類輸入,例如搜索框、評論框、文章內容等等。html

結果在 segmentfault 閱讀評論時看到了一個連接一點直接把我給滾動到頂部,頓時心中一陣 慘叫雙手捶胸 後把頁面拉回評論並打開了 控制檯 查看了連接爲什麼方神聖:java

<a href="#">...</a>
複製代碼

頓時又是一陣 慘叫雙手捶胸 原來 segmentfault 評論是支持 markdown 語法的,若是再評論裏輸入 [...](#) 則會被轉換成如上代碼。git

好奇心突發跑到了 掘金 測試了一下帶鏈接的評論,打開 控制檯 看了看因爲使用了 target="_blank" 沒有出現被傳送到頂部的狀況,內心暗暗道 喵哉 🐱 之後仍是得當心行事,碰巧每日30秒正愁不知道寫什麼那就來寫寫 回到頂部 吧。github

回到頂部

第一種寫法就介紹一下今天被中全套的代碼,利用了 錨點 來實現回到頂部:segmentfault

<a href="#"回頂部></a>
複製代碼

若是須要滾動到別的元素可使用 id 屬性配合 錨點 來實現:瀏覽器

<header id="header">我是頭部</header>
<a href="#header">回到頁面頭部</a>
複製代碼

不過因爲這種方法 滾動 得太快了,性能確定是很好就是體驗不怎麼好。不過咱們可使用 css 的 scroll-behavior 屬性來提高體驗:微信

html, body {
  scroll-behavior: smooth;
}
複製代碼

雖然第一種方法配合 css 的 scroll-behavior 屬性顯得挺不錯,可是 scroll-behavior 兼容性挺不高的具體能夠看 caniusemarkdown

迴到頂部

因爲在頁面垂直滾動過程當中會改變 window.scrollY 的值,第二種即是寫法利用 window.scrollTo() 把它設置爲 0 來實現回到頂部:

window.scrollTo(0, 0)
複製代碼

不過這樣使用也會致使 滾動 得太快帶來的體驗很差,這個時候咱們能夠利用 window.requestAnimationFrame() 告訴瀏覽器——你但願執行一個動畫,而且要求瀏覽器在下次重繪以前調用指定的回調函數更新動畫,該方法須要傳入一個回調函數做爲參數,該回調函數會在瀏覽器下一次重繪以前執行。

這裏使用裏一個來判斷當頁面沒有滾動到頂部時循環調用 window.requestAnimationFrame 來進行逐步滾動,每次滾動的距離 c - c / 8 隨着 c 的減少而減少進而實現滾動效果:

const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};
複製代碼

不過繼續查閱 caniuse 中的 window.requestAnimationFrame() 在主流瀏覽器中支持挺好的,可是須要兼容 ie6-9 的同窗就得另外尋找方法了。仔細想一想 window.requestAnimationFrame()setTimeout() 好像有點類似。

window.requestAnimationFrame 回調函數執行次數一般是每秒60次即一秒60幀,將 setTimeout 執行的頻率也設置爲同樣的就好了:

if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = function (callback) {
        return setTimeout(callback, 1000 / 60);
    }
}

const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};
複製代碼

搞定神器 ie6-9 的兼容問題。

囬到頂部

第三種寫法使用函數 Element.scrollIntoView() 能夠將選中的元素移動到 可視區域可視區域 更多相關知識點能夠看以前的一篇文章 巧用可視區域

document.querySelector('body')
    .scrollIntoView({
        behavior: 'smooth',
        block: 'start',
    })
複製代碼

代碼實現比起第三種簡單了很多,當 css 的 scroll-behavior 被設置時會默認設置 Element.scrollIntoView()behavior,依舊打開 caniuse 查看兼容性會發現和 window.requestAnimationFrame() 比起來差不了多少,在神器 ie6-9 也有兼容問題。

囘到頂部

第四種方法將前面方法進行一個整合,頁面支持 Element.scrollIntoView() 則直接使用第三種方法,若是頁面不支持則使用第二種方法。對於 Element.scrollIntoView() 的支持利用到了 window.getComputedStyle() 也有兼容性問題須要判斷一下:

let scrollToTop;

if (window.getComputedStyle && window.getComputedStyle(document.body).scrollBehavior) {
    scrollToTop = () => document.querySelector('body')
        .scrollIntoView({
            behavior: 'smooth',
            block: 'start',
        });
} else {
    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function (callback) {
            return setTimeout(callback, 1000 / 60);
        }
    }

    scrollToTop = () => {
        const c = document.documentElement.scrollTop || document.body.scrollTop;
        if (c > 0) {
            window.requestAnimationFrame(scrollToTop);
            window.scrollTo(0, c - c / 8);
        }
    };
}
複製代碼

在開發中要注意瀏覽器的兼容性,多使用 caniuse 來幫助咱們參看兼容性狀況。並根據產品的開發需求來書寫代碼,例如不須要兼容 ie6-9 時咱們能夠直接使用 Element.scrollIntoView()。在剛纔的學習中除了學習了回到頂部外,只需再學習一下獲取元素所在 y 軸座標或者高度就會 一不當心順手 學習了滾動到頁面各處。

一塊兒成長

在困惑的城市裏總少不了並肩同行的 夥伴 讓咱們一塊兒成長。

  • 若是您想讓更多人看到文章能夠點個 點贊
  • 若是您想激勵小二能夠到 Github 給個 小星星
  • 若是您想與小二更多交流添加微信 m353839115

微信公衆號

本文原稿來自 PushMeTop

相關文章
相關標籤/搜索