本文介紹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)
完成!👏👏👏