本文介紹Hamsterism使用的回到頁首的組件設計
由於監聽使用者scroll event勢必在client端
因此在製作成SSR或static時要注意加入<client-only>包起來防呆
程式碼如下
<template> <client-only> <div v-show="isVisible" class="scrollup-button" @click="scrollToTop"> <img src="~/static/icons/double-arrow-white.svg" alt="back to top" /> </div> </client-only> </template> <script> import { debounce } from 'vue-debounce' export default { data() { return { scrollTop: null, isVisible: false, visibleDistance: 200, } }, mounted() { window.addEventListener('scroll', debounce(this.scrollListener, 100), true) }, beforeDestroy() { window.removeEventListener('scroll', this.scrollListener) }, methods: { scrollListener() { if (window.pageYOffset) { this.scrollTop = window.pageYOffset } else { this.scrollTop = 0 } // 控制按鈕顯示 if (this.scrollTop > this.visibleDistance) { this.isVisible = true } else { this.isVisible = false } }, scrollToTop() { this.intervalId = setInterval(() => { if (window.pageYOffset === 0) { clearInterval(this.intervalId) } window.scroll(0, window.pageYOffset - 200) }, 10) }, }, } </script> <style lang="scss" scoped> .scrollup-button { position: fixed; bottom: 4rem; right: 2rem; cursor: pointer; background-color: $hamsterism-bg-color-primary-light; border-radius: 0.25rem; opacity: 0.6; padding: 0.5rem; z-index: 1000; transition: opacity 0.15s ease; &:hover { opacity: 0.9; } img { width: 2rem; height: 2rem; } } </style>
監聽函數scrollListener()
,就是抓當前位置用的,判斷是否顯示button
window.pageYOffset
變數說明請參見MDN
在mounted()時於window
添加位置監聽函數,注意這裡的debounce!!!
如果沒有debounce function,使用者一滾動,就會觸發幾十幾百個scroll event
這會降低google網頁效能分數Ovo
此外須注意的就是養成組件destroy前,執行removeEventListener的好習慣
回到頂端的function為scrollToTop()
原理很簡單,當前距頂位置大於零時,觸發window.scroll()
,公式說明可見MDN
透過setInterval()
不斷向上滾動,直到回到頂端
window.pageYOffset
變成0,clearInterval(this.intervalId)
滾動的快慢取決於window.scroll()
內一次向上滾多少距離(我是設200)
完成!👏👏👏