Back to Top Button Component in Nuxt

Nuxt
back-to-top

本文介紹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)



完成!👏👏👏


© 2021 Hamsterism. All rights reserved github