解決 Vue.js 應用中返回首頁時滾動位置不對的問題


滾動位置的問題

在一個專案中,我們需要從詳細頁面返回首頁時保持滾動位置。這個問題看起來很簡單,但處理起來還是有點棘手。

每次從詳細頁面返回首頁時,頁面都會滾動到頂部,而不是返回到點擊「了解更多」按鈕時的滾動位置。這樣使用者體驗不太好,尤其頁面很長時。

解決過程

先保存當前頁面的滾動位置,然後在返回首頁時恢復。

router/index.js

import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  { path: '/', name: 'home', component: HomeView },
  { path: '/detail/:id', name: 'detail', component: DetailView }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

router.afterEach((to, from) => {
  if (to.name === 'home' && from.meta.scrollPosition) {
    // 不重置滾動位置,讓 scrollToContent 處理滾動
  } else {
    window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
  }
});

export default router;

DetailView.vue:點擊時保存滾動位置

<template>
  <div>
    <button @click="navigateToHome">返回首頁</button>
  </div>
</template>

<script setup>
import { useRouter, useRoute } from 'vue-router';

const router = useRouter();
const route = useRoute();

const navigateToHome = () => {
  const scrollPosition = { top: window.scrollY, left: window.scrollX };
  route.meta.scrollPosition = scrollPosition;
  router.push({ name: 'home' });
};
</script>

HomeView.vue:恢復到保存的位置

<script setup>
import { onMounted, nextTick } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();

const scrollToContent = async () => {
  await nextTick();
  const savedPosition = route.meta.scrollPosition;
  if (savedPosition) {
    window.scrollTo({ top: savedPosition.top, left: savedPosition.left, behavior: 'smooth' });
  }
};

onMounted(() => {
  scrollToContent();
});
</script>

結語

這個過程讓我學到不少,尤其是如何在 Vue Router 中保存和恢復滾動位置。如果你在專案中遇到類似問題,可以試試這種方法。