代码如下
export function useAutoScroll(key: string) {
// 记录滚动条位置, 这里直接使用Nuxt3自带的useState方法, 使用本地存储, Pinia, Vuex之类都可以
const scrollTop = useState<number>(key)
// 离开页面时, 记录滚动条的位置
onBeforeRouteLeave((to, from, next) => {
scrollTop.value = Math.max(window.scrollY, document.documentElement.scrollTop, document.body.scrollTop)
next()
})
// 页面挂载成功后, 恢复滚动条位置
onMounted(() => {
console.log('onMounted', scrollTop.value)
if (scrollTop.value) {
setTimeout(() => {
window.scrollTo(0, scrollTop.value)
}, 50)
}
})
// 如果页面使用keep-alive, 那么onMouted是不执行的, 则需要好下方方法
onActivated(() => {
console.log('onActivated', scrollTop.value)
if (scrollTop.value) {
setTimeout(() => {
window.scrollTo(0, scrollTop.value)
}, 50)
}
})
}
使用方法
import useAutoScroll from '@/xxx.ts'
// 传入一个唯一性的key
useAutoScroll('frontend-index')
配合el-scrollbar使用
// composables/scroll.ts
import type ElScrollbar from 'element-plus/es/components/scrollbar'
import { templateRef } from '@vueuse/core'
export type ScrollbarInstance = InstanceType<typeof ElScrollbar>
/**
* 自动记录/恢复滚动条位置
* @param key 组件ref名称
* @returns 设置滚动条函数
*/
export function useAutoScroll(key: string) {
const scrollTop = useState<number>(key)
function onScroll(event: { scrollLeft: number; scrollTop: number }) {
scrollTop.value = event.scrollTop
}
onMounted(() => {
const scrollBar = templateRef(key) as unknown as Ref<Pick<ScrollbarInstance, 'setScrollTop'>>
if (scrollTop.value)
scrollBar.value?.setScrollTop(scrollTop.value)
})
onActivated(() => {
const scrollBar = templateRef(key) as unknown as Ref<Pick<ScrollbarInstance, 'setScrollTop'>>
if (scrollTop.value)
scrollBar.value?.setScrollTop(scrollTop.value)
})
return {
onScroll,
}
}
<template>
<el-scrollbar ref="listScrollBar" @scroll="onScroll">
//
</el-scrollbar>
</template>
<script setup lang="ts">
import type { ScrollbarInstance } from '~/composables/scroll'
// 传入el-scrollbar的ref
const { onScroll } = useAutoScroll('listScrollBar')
</script>