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保持一致

相关推荐
itmigrate7 小时前
前端项目里,Object.is 并不是 === 的平替
前端
小大宇8 小时前
Vue知识点6-computed计算属性
前端·javascript·vue.js
程序员海军8 小时前
尤雨溪 : Vue 4 已经在规划中了!
前端·javascript·vue.js
2601_949970699 小时前
HumanizeDuration 跨端三方库仓颉适配全流程
前端·javascript·flutter
风骏时光牛马10 小时前
后端服务接口开发与性能优化
前端
kyriewen11 小时前
我让 4 个 AI 互相 review 代码,最温柔的那个下手最狠
前端·程序员·ai编程
计算机魔术师11 小时前
493家公司白砸AI钱?Apollo这组数据戳破了幻觉
前端
IT_陈寒11 小时前
Java静态变量初始化坑得我头皮发麻
前端·人工智能·后端
天外飞雨道沧桑11 小时前
我在浏览器里练了一个 792 参数的大模型,它学会了补全 JavaScript
开发语言·javascript·ai·ecmascript·ai编程
柳杉11 小时前
用 Codex 完成智慧高速 3D 可视化大屏,从 18 张行业设计稿到可交互的运行监测中心
前端·ai编程·数据可视化