Tab 数据切换保持滚动条的位置 hooKs

237 阅读1分钟

hooks

import type { Ref } from 'vue'
import { unref } from 'vue'

export function useScrollRecover(el: Ref<HTMLElement | undefined>) {
    // 用于记录滚动位置的变量
    const scrollTop = ref(0)

    // 滚动响应处理函数,在事件中记录滚动位置
    const onScroll = () => {
      scrollTop.value = unref(el)?.scrollTop || 0
    }

    // mounted时监听scroll事件
    onMounted(() => {
      unref(el)?.addEventListener('scroll', onScroll)
    })

    // keep-alive激活时会自动调用actived钩子,此时将容器的滚动高度设置为记录的值
    onActivated(() => {
        (unref(el) as HTMLElement).scrollTop = unref(scrollTop)
    })

    // unmounted时记得取消监听
    onUnmounted(() => {
      unref(el)?.removeEventListener('scroll', onScroll)
    })
  }

页面

<template>
        <div>
                <keep-alive>
                        <div ref="containerRef">
                                <el-tabs v-model="activeTab" @tab-click="handleTabClick">
                                        <el-tab-pane v-for="item in tabs" :key="item.id" :label="item.label" :name="item.name">
                                                <div style="height: 200px; overflow-y: auto" @scroll.up="handleScroll">
                                                        <div v-for="child in item.children" :ref="child.ref" :key="child.id">
                                                                <p>{{ `${item.name}-${child.label}` }}</p>
                                                        </div>
                                                </div>
                                        </el-tab-pane>
                                </el-tabs>
                        </div>
                </keep-alive>
        </div>
</template>
<script setup lang="ts">
import { useScrollRecover } from './components/DialogMap/useScrollRecover'
const containerRef = ref<HTMLElement>()
useScrollRecover(containerRef)
const tabs = ref([
        {
                id: 1,
                label: '终端客户',
                name: '终端客户',
                children: [],
        },
        {
                id: 2,
                label: '渠道客户',
                name: '渠道客户',
                children: [],
        },
        {
                id: 3,
                label: '测试客户',
                name: '测试客户',
                children: [],
        },
])
const activeTab = ref('终端客户')
/**
 * 点击事件
 * @param tab 点击的tab
 * @description 当点击tab时,保存当前tab的滚动位置,并更新activeTab的值
 */
const handleTabClick = (tab: any) => {
        activeTab.value = tab.paneName
}
/**
 * @scroll.up 向上滚动
 * @scroll.down 向下滚动
 * @param tabName tab名称
 */
const handleScroll = (tabName) => {
        console.log('Tab', tabName, 'has been scrolled')
}
onMounted(() => {
        tabs.value.forEach((item: any) => {
                for (let index = 0; index < 200; index++) {
                        item.children.push({
                                name: `child-${index}`,
                                label: `child-${index}`,
                                content: `child-${index}`,
                                disabled: false,
                        })
                }
        })
})
</script>
```