vue3 keepAlive+记录滚动条

store

javascript 复制代码
import { defineStore } from 'pinia'

export const useCachedViewsStore = defineStore('cachedViews', {
    state: () => ({
        // 存储的是组件的 name,不是路由 path
        cachedViews: [] as string[]
    }),

    actions: {
        /** 添加缓存(路由守卫中调用) */
        addCachedView(name: string) {
            if (name && !this.cachedViews.includes(name)) {
                this.cachedViews.push(name)
            }
        },

        /** 移除指定缓存(关闭标签页/编辑后返回时调用) */
        removeCachedView(name: string) {
            const index = this.cachedViews.indexOf(name)
            if (index > -1) {
                this.cachedViews.splice(index, 1)
            }
        },

        /** 清空所有缓存(退出登录时调用) */
        clearAllCachedViews() {
            this.cachedViews = []
        }
    }
})

App.vue

javascript 复制代码
<template>
    <router-view v-slot="{ Component, route }">
        <keep-alive :include="cachedViews">
            <component :is="Component" :key="route.fullPath"/>
        </keep-alive>
    </router-view>
</template>

<script setup lang="ts">
    import {computed} from 'vue'
    import {useCachedViewsStore} from '@/store'

    const cachedViewsStore = useCachedViewsStore()
    const cachedViews = computed(() => cachedViewsStore.cachedViews)
</script>

router

javascript 复制代码
import {createRouter, createWebHashHistory} from 'vue-router'
import routes from './routes'
import {useCachedViewsStore} from '@/store'

const asmnPosition = {}
const router = createRouter({
    history: createWebHashHistory(`/#/${import.meta.env.VITE_PROJECT_NAME}/`),
    routes,
    scrollBehavior(to, from, savedPosition) {
        if (needKeepAlive(to)) {
            // savedPosition 是浏览器前进/后退时记录的位置
            if (savedPosition) {
                return savedPosition
            }
            // 代码 push 跳转,读取 asmnPosition 中保存的位置
            const top = asmnPosition[to.name]
            if (top)
                return {top}
        }
        // 滚动到顶部
        return {top: 0}
    }
})

router.beforeEach((to, from, next) => {
    const cachedViewsStore = useCachedViewsStore()
    if (needKeepAlive(to))
    // 注意:这里传入的是路由 name,必须和组件 name 保持一致!
        cachedViewsStore.addCachedView(to.name)

    if (needKeepAlive(from))
        asmnPosition[from.name] = window.scrollY

    next()
})


function needKeepAlive(to) {
    return to.meta.keepAlive && to.name
}

export default router

router

javascript 复制代码
const routes = [
    {
        path: '/',
        // keepAlive时name必须和组件 name 保持一致!
        name: 'home',
        component: () => import( '@/views/Home.vue'),
        meta: {
            keepAlive: true,
        }
    },
    {
        path: '/test',
        name: 'test',
        component: () => import( '@/views/Test.vue'),
    },
]

export default routes

home.vue

javascript 复制代码
<template>
    <div class="flex-center">
        <div class="a">
            <div class="b">slave-home</div>
        </div>
        <router-link to="/test">测试页</router-link>
        <div v-for="(v, i) in 100">
            {{v}}
        </div>
    </div>

    <HomeTabbar/>
</template>

<script setup lang="ts">
    import {ref} from 'vue'
    import HomeTabbar from '@/components/HomeTabbar/Index.vue'

		// 定义当前组件的name,同vue2的name
    defineOptions({
        name: 'home'
    })

    const active = ref('0')

    console.log('asmn')
</script>

<style lang="scss" scoped>
    .a {
        .b {
            color: red;
        }
    }
</style>

通过来回切换页面 Home --> Test ---> Home,看有无日志"asmn"输出,判断keepAlive是否生效,相当于有输出代表生效,即页面内的组件在test -> push -> Home回来的时候没被销毁。

keepAlive无法记录滚动条,所以也单独处理了,可观察切换回来时,滚动条是否与上次一致。

注意:使用keepAlive与记录滚动条,router里面的name需要与组件的name保持一致

相关推荐
福兮说8 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理9 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
专业程序开发源9 小时前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
专业程序开发源10 小时前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
小呆呆66610 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人10 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)10 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan11 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_11 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒11 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端