• nuxt3正确使用keepalive页面缓存组件缓存


    最近使用 nuxt@3.x 版本做SEO优化项目比较多,之前也踩坑过,所以记录一下在 nuxt3 中路由缓存的正确使用方法,本人也之前在GitHub社区中提交过反馈问题,最后是在 3.8.2 版本解决了路由缓存问题。下面讲解如何正确使用keepalive做到页面缓存,组件缓存。

    # 环境版本如下
    node # 21.4.0
    nuxt # 3.12.3
    vue # latest  目前最新版本 3.4.*
    

    页面缓存

    keepalive 我们知道都是用来缓存组件 在组件卸载的时候 并不去真正意义上的销毁,而是隐藏掉。等再次挂载的时候再把它显示出来。其组件的状态保持原有的状态,并不会初始化。写多了 vue 项目的小伙伴们,大部分通过路由文件( src/router.js )定义 name 值,再去 router-view 组件里包裹 keepalive 组件去判断 路由里面的 name 值去使用。但是在 nuxt 框架内不需要这么复杂的操作。

    • app.vue文件内容
    
    <template>
        <div>
            
            <NuxtPage :keepalive />
        div>
    template>
    <script lang="ts" setup>
        // keepalive 所需的参数 指定name值为index 的页面 进行缓存
        const keepalive = {
            include: ["index"],
        };
    script>
    
    • pages文件夹
    pages
    ├─index.vue # 若组件未定义name值 则为 文件名 index
    └─user.vue # name为user
    
    • index.vue文件内容
    <template>
        <div>indexdiv>
        <p>data: {{ data }}p>
        <p>
            <button @click="data++">+1button>
            <button @click="data--">-1button>
        p>
        <p class="links">
            <NuxtLink to="/user">user PageNuxtLink>
        p>
    template>
    <script setup lang="ts">
        const data = ref(0);
    script>
    

    项目启动路径为 http://localhost:3000/ 的时候,此时,在组件内操纵 data 的值变化,再去跳转 http://localhost:3000/user 时,再跳回 http://localhost:3000/data 的值不会初始化,而是切换 /user 路由前页面的状态。此时使用 onActivated api来监听组件被激活。

    <script lang="ts" setup>
        onActivated(() => {
            console.log("onActivated 页面激活了!");
        });
    script>
    
    • 路径复杂的请使用defineOptions指定组件name值,以免使用路由缓存失败!

    例如:pages/userData.vuepages/news/detailpages/news/[id].vue。这几个路径过于复杂,在 NuxtPage 组件中难以使用 include 属性值去判断缓存条件,所以需要在页面文件中声明该页面的组件 name 值。

    
    <script setup lang="ts">
    defineOptions({
      name: "IndexPage", 
    }); 
    script>
    
    
    <script setup lang="ts">
    defineOptions({
      name: "newsDetail", 
    }); 
    script>
    
    
    <template>
    
        <div>
            <NuxtPage :keepalive />
        div>
    
    template>
    <script lang="ts" setup>
    
        const keepalive = {
            include: ["IndexPage","newsDetail"], 
            // 对应 pages/index.vue ,pages/news/detail.vue 中的 name 值 缓存路由
        };
    
    script>
    
    

    组件缓存

    如果在页面中,使用了v-if指令来控制组件显示,如何保证组件数据不被销毁。当然还是使用keepalive组件。假设我们在components文件中定义组件,会自动全局导入,无需引用。

    components
    ├─Val
    │  └─Input.vue # 若组件未定义name值 则为 文件名 Input
    ├─Counter.vue # 若组件未定义name值 则为 文件名 Counter
    └─TextTip.vue # name 为 TextTip
    
    
    <template>
        <div class="counter">
            <h2>counterh2>
            <p>data:{{ data }}p>
            <p>
                <button @click="data++">+1button>
                <button @click="data--">-1button>
            p>
        div>
    template>
    
    <script lang="ts" setup>
        const data = ref(0);
    script>
    <style scoped>
        .counter {
            padding: 20px;
        }
    style>
    
    
    <template>
        <div class="text-tip">
            <h2>text-tiph2>
            <p>text: {{ text }}p>
            <p>
                <button @click="text += '1'">add Textbutton>
            p>
        div>
    template>
    <script lang="ts" setup>
        const text = ref("text-1");
    script>
    
    
    <template>
        <div>indexdiv>
        <p>
            <button @click="showCounter = !showCounter">
                {{ !showCounter ? "显示Counter" : "显示TextTip" }}
            button>
        p>
        <hr />
        <KeepAlive :include="keep.include">
            <Counter v-if="showCounter" />
            <TextTip v-else />
        KeepAlive>
    template>
    <script setup lang="ts">
        const showCounter = ref(false);
        const keep = {
            include: ["Counter"],
        };
    script>
    

    此时点击 显示Counter 按钮,在 Counter 组件中操作内部数据改变 data:5 ,点击按钮再去切换组件显示隐藏,会发现 Counter 组件并不会销毁掉之前的值 data:5 ,而TextTip组件在操作内部的数据改变后切换 隐藏/显示 后, text 数据是初始化的值 text-1

    • 注意components文件定义的组件name值

    components/Counter.vuecomponents/Val/Input.vuename 值nuxt自动会给组件的name值取为文件名 CounterInput 。而在组件自动导入的时候却是使用 。会有点迷惑,所以请在使用 组件包裹来缓存状态,请务必使用 defineOptions 指定组件的name值。

    
    <template>
        <div class="input-warpper">
            <h2>Inputh2>
            <input v-model="val" />
        div>
    template>
    <script lang="ts" setup>
        const val = ref("");
        defineOptions({
            name: "ValInput"
        })
    script>
    <style>
        .input-warpper {
            margin: 20px;
        }
    style>
    

    或者使用 export default { name:'xxx' } 来指定组件的name值,不使用 setup 语法。

    
    <template>
        <div class="input-warpper">
            <h2>Inputh2>
            <input v-model="val" />
        div>
    template>
    <script lang="ts" setup>
        const val = ref("");
    script>
    <script lang="ts">
        export default {
            name: "ValInput"
        }
    script>
    <style>
        .input-warpper {
            margin: 20px;
        }
    style>
    

    案例地址

    点击这里跳转代码案例,来调试 keepalive 页面缓存 和 组件缓存

    推荐环境版本: node v21.4.0 , nuxt v3.12.* , 使用 pnpm 安装依赖

  • 相关阅读:
    对某钓鱼样本分析
    pycharm运行命令的时候出现的问题
    Python接口自动化搭建过程,含request请求封装
    从0-1,使用腾讯OCR进行身份证识别
    【数据结构】数组和字符串(七):特殊矩阵的压缩存储:三元组表的转置、加法、乘法操作
    MATLAB求极限
    深度学习笔记(3)——pytorch+TextCNN实现情感分类(外卖数据集)
    websocket实现一个局域网在线摸鱼聊天室
    Win10怎么把登录密码去掉
    【Elasticsearch专栏 02】深入探索:Elasticsearch为什么使用倒排索引而不是正排索引
  • 原文地址:https://www.cnblogs.com/kongyijilafumi/p/18293976