Vue頁面返回滾動(dòng)位置恢復(fù)(keep-alive滾動(dòng)記憶)
在Vue單頁應(yīng)用開發(fā)中,我們經(jīng)常會(huì)遇到這樣的場景:用戶在一個(gè)長列表頁面滾動(dòng)瀏覽了若干項(xiàng)后,點(diǎn)擊進(jìn)入詳情頁,然后返回期望能夠回到之前的滾動(dòng)位置,而不是重新回到頁面頂部。這種用戶體驗(yàn)的優(yōu)化對(duì)于內(nèi)容型應(yīng)用尤為重要。
Vue的<keep-alive>組件可以緩存頁面狀態(tài),但它并不自動(dòng)保存和恢復(fù)滾動(dòng)位置。今天我們就來探討一種優(yōu)雅的解決方案。
核心代碼解析
import { onActivated, ref } from "vue";
import { onBeforeRouteLeave } from "vue-router";
export function useScroll(targetRef) {
const scrollTop = ref(0);
onActivated(() => {
if (targetRef.value) {
targetRef.value.scrollTop = scrollTop.value
}
})
onBeforeRouteLeave(() => {
if (targetRef.value) {
scrollTop.value = targetRef.value.scrollTop
}
})
}
這個(gè)自定義組合式函數(shù)useScroll雖然代碼簡潔,但功能強(qiáng)大且完整。讓我們分解一下它的工作原理:
1. 響應(yīng)式狀態(tài)管理
使用ref(0)創(chuàng)建了一個(gè)響應(yīng)式的scrollTop變量,用于存儲(chǔ)滾動(dòng)位置。
2. 生命周期鉤子運(yùn)用
onActivated: 當(dāng)被<keep-alive>緩存的組件激活時(shí)調(diào)用,用于恢復(fù)滾動(dòng)位置onBeforeRouteLeave: 在路由離開之前調(diào)用,用于保存當(dāng)前滾動(dòng)位置
3. 引用DOM元素
通過targetRef參數(shù)接收一個(gè)DOM元素的引用,這使得函數(shù)可以靈活應(yīng)用于任何可滾動(dòng)元素
完整使用示例
<template>
<div class="product-list" ref="scrollTarget">
<div v-for="product in products" :key="product.id" class="product-item">
<h3>{{ product.name }}</h3>
<p>{{ product.description }}</p>
<button @click="goToDetail(product)">查看詳情</button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useScroll } from '@/composables/useScroll'
const router = useRouter()
const scrollTarget = ref(null)
const products = ref([...]) // 產(chǎn)品列表數(shù)據(jù)
// 使用滾動(dòng)記憶功能
useScroll(scrollTarget)
const goToDetail = (product) => {
router.push(`/product/${product.id}`)
}
</script>
<style scoped>
.product-list {
height: 100vh;
overflow-y: auto;
}
</style>
路由配置要點(diǎn)
為了使<keep-alive>生效,需要在路由配置和組件渲染中做相應(yīng)設(shè)置:
// router.js
const routes = [
{
path: '/products',
component: () => import('@/views/ProductsView.vue'),
meta: { keepAlive: true } // 添加元信息標(biāo)識(shí)需要緩存的頁面
}
// ...其他路由
]
<!-- App.vue -->
<template>
<router-view v-slot="{ Component, route }">
<keep-alive>
<component
:is="Component"
v-if="route.meta.keepAlive"
:key="route.name"
/>
</keep-alive>
<component
:is="Component"
v-if="!route.meta.keepAlive"
:key="route.name"
/>
</router-view>
</template>
進(jìn)階優(yōu)化
1. 多滾動(dòng)容器支持
實(shí)際應(yīng)用中,一個(gè)頁面可能有多個(gè)滾動(dòng)區(qū)域,我們可以擴(kuò)展useScroll來支持這種情況:
export function useScroll(targetRef, identifier = 'default') {
const scrollPositions = ref({});
onActivated(() => {
if (targetRef.value) {
targetRef.value.scrollTop = scrollPositions.value[identifier] || 0;
}
})
onBeforeRouteLeave(() => {
if (targetRef.value) {
scrollPositions.value[identifier] = targetRef.value.scrollTop;
}
})
}
2. 防抖處理
對(duì)于高頻觸發(fā)滾動(dòng)事件的情況,可以添加防抖優(yōu)化:
import { debounce } from 'lodash-es';
export function useScroll(targetRef) {
const scrollTop = ref(0);
onActivated(() => {
if (targetRef.value) {
targetRef.value.scrollTop = scrollTop.value;
}
})
const saveScrollPosition = debounce(() => {
if (targetRef.value) {
scrollTop.value = targetRef.value.scrollTop;
}
}, 100);
onMounted(() => {
if (targetRef.value) {
targetRef.value.addEventListener('scroll', saveScrollPosition);
}
});
onUnmounted(() => {
if (targetRef.value) {
targetRef.value.removeEventListener('scroll', saveScrollPosition);
}
});
}
到此這篇關(guān)于Vue頁面返回滾動(dòng)位置恢復(fù)(keep-alive滾動(dòng)記憶)的文章就介紹到這了,更多相關(guān)Vue 滾動(dòng)位置恢復(fù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 解決Vue頁面固定滾動(dòng)位置的處理辦法
- Vue實(shí)現(xiàn)渲染數(shù)據(jù)后控制滾動(dòng)條位置(推薦)
- vue實(shí)現(xiàn)滾動(dòng)條到頂部或者到指定位置
- vue中實(shí)現(xiàn)點(diǎn)擊按鈕滾動(dòng)到頁面對(duì)應(yīng)位置的方法(使用c3平滑屬性實(shí)現(xiàn))
- vue監(jiān)聽頁面中的某個(gè)div的滾動(dòng)事件并判斷滾動(dòng)的位置
- Vue滾動(dòng)到指定位置的多種方式示例詳解
- Vue滾動(dòng)頁面到指定位置的實(shí)現(xiàn)及避坑
- Vue列表如何實(shí)現(xiàn)滾動(dòng)到指定位置樣式改變效果
- 解決vue無法設(shè)置滾動(dòng)位置的問題
- vue通過滾動(dòng)行為實(shí)現(xiàn)從列表到詳情,返回列表原位置的方法
- vue-scroller記錄滾動(dòng)位置的示例代碼
相關(guān)文章
vue3實(shí)現(xiàn)點(diǎn)擊空白區(qū)域隱藏div
這篇文章主要介紹了vue3實(shí)現(xiàn)點(diǎn)擊空白區(qū)域隱藏div方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
關(guān)于vue中@click.native.prevent的說明
這篇文章主要介紹了關(guān)于vue中@click.native.prevent的說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
elementui導(dǎo)出數(shù)據(jù)為xlsx、excel表格
本文主要介紹了elementui導(dǎo)出數(shù)據(jù)為xlsx、excel表格,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Vue使用Sentry實(shí)現(xiàn)錯(cuò)誤監(jiān)控
Sentry?是一款功能強(qiáng)大的開源錯(cuò)誤監(jiān)控服務(wù),廣泛用于追蹤和修復(fù)應(yīng)用中的異常情況,本文將詳細(xì)介紹如何在?Vue?應(yīng)用中集成和使用?Sentry,感興趣的可以了解下2024-11-11
vue利用Moment插件格式化時(shí)間的實(shí)例代碼
Moment.js 是一個(gè) JavaScript 日期處理類庫,用于解析、檢驗(yàn)、操作、以及顯示日期。這篇文章主要給大家介紹了關(guān)于vue利用Moment插件格式化時(shí)間的相關(guān)資料,需要的朋友可以參考下2021-05-05
vue實(shí)現(xiàn)圖片加載完成前的loading組件方法
下面小編就為大家分享一篇vue實(shí)現(xiàn)圖片加載完成前的loading組件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-02-02
element-ui動(dòng)態(tài)級(jí)聯(lián)選擇器回顯問題詳解(二十多行代碼搞定)
大家在使用element-ui的時(shí)候肯定會(huì)遇到這樣一個(gè)問題,就是在你使用級(jí)聯(lián)選擇器的回顯問題,下面這篇文章主要給大家介紹了關(guān)于element-ui動(dòng)態(tài)級(jí)聯(lián)選擇器回顯問題的相關(guān)資料,需要的朋友可以參考下2023-03-03
vue3中使用reactive定義的變量響應(yīng)式丟失問題解決方案
這篇文章主要介紹了vue3中使用reactive定義的變量響應(yīng)式丟失問題的具體例子和解決方案,文章通過代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-06-06

