vue3 keepalive缓存问题

有三个页面,upload到chart到three,我想实现chart到three ,返回时chart缓存不刷新,upload到chart时,chart不缓存,这个怎么实现哎,我没有使用vuex,更改keepalive状态总是不行
app.vue


<template>
 
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component
        :is="Component"
        v-if="$route.meta.keepAlive"
        :key="$route.name"
      ></component>
    </keep-alive>
    <component
      :is="Component"
      v-if="!$route.meta.keepAlive"
      :key="$route.name"
    ></component>
  </router-view>
 
</template>
 
<script  lang="ts">
import { defineComponent } from "vue";
 
export default defineComponent({
  name: "App",
  setup() {},
});
</script>
 
<style scoped>
</style>

router.ts

 
```javascript
import chart from '@/views/ChartView.vue'
import { createRouter, createWebHistory, onBeforeRouteLeave } from 'vue-router'
 
 
 
const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/',
            name: 'home',
            component: () => import('@/views/HomeView.vue')
        },
        {
            path: '/upload',
            name: 'upload',
            component: () => import('@/views/UploadView.vue')
        },
        {
            path: '/test',
            name: 'test',
            component: () => import('@/views/test.vue')
        },
        {
            path: '/chart',
            name: 'chart',
            component: () => import('@/views/ChartView.vue'),
            meta: {
                keepAlive: true
            }
        },
        {
            path: '/three',
            name: 'three',
            component: () => import('@/views/ThreeView.vue'),
            meta: {
                keepAlive: false
            }
 
        },
        {
            path: '/empty',
            name: 'empty',
            component: () => import('@/views/EmptyView.vue')
        }
 
    ]
})
 
// router.beforeEach((to, from, next) => {
//     console.log('to:', to)
//     console.log('from:', from)
//     if (from.path == '/chart' && to.path == '/upload') {
//         from.meta.keepAlive = false
 
//     }
//     console.log('from:', from)
 
//     next();
// });
 
export default router
 
 

你这个问题需要在路由间传递参数来控制缓存。

首先你可以给 chart 页面配置一个 noCache 参数,标记该页面是否需要缓存:

{
    path: '/chart',
    name: 'chart',
    component: () => import('@/views/ChartView.vue'),
    meta: {
        noCache: false // 默认需要缓存
    }
}

在跳转到 /three 页面时,设置 noCache 参数为 true,同时在 three 页面中监听路由变化,在返回时手动刷新 /chart 页面:

import { onBeforeRouteLeave, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'

export default {
  setup() {
    const router = useRouter()
    const shouldRefresh = ref(false)

    onMounted(() => {
      router.beforeEach((to, from) => {
        if (from.name == 'three' && to.name == 'chart' && shouldRefresh.value) {
          router.replace({ name: 'empty' })
          // 手动刷新页面
          setTimeout(() => {
            router.replace({ name: 'chart' })
            shouldRefresh.value = false
          }, 0)
          return false
        }
      })
    })

    onBeforeRouteLeave(() => {
      if (router.currentRoute.value.name == 'three') {
        shouldRefresh.value = true
      }
    })
  }
}

最后是 upload 到 chart 时,chart 不缓存。这个我不太确定是否有必要,因为如果 meta.keepAlive 属性为 false,chart 页面在离开时已经被销毁了,再进入时就不存在缓存问题了。如果确实需要这个功能,可以在 upload 页面路由跳转时,修改 /chart 路由的 meta.keepAlive 属性即可:

router.beforeEach((to, from, next) => {
  if (from.name == 'upload' && to.name == 'chart') {
    const chartRoute = router.getRoutes().find(route => route.name == 'chart')
    if (chartRoute) {
      chartRoute.meta.keepAlive = false
    }
  }
  next()
})

上面代码中找到了 /chart 路由,并将其 meta.keepAlive 属性修改为了 false。需要注意的是,这样做修改的是路由配置,如果你需要立即生效,需要使用 router.replace({ name: 'chart' }) 重新跳转到 /chart 页面。

在路由配置中使用meta属性来控制缓存行为

const routes = [
  {
    path: '/upload',
    name: 'Upload',
    component: Upload,
    meta: {
      keepAlive: false // 不缓存
    }
  },
  {
    path: '/chart',
    name: 'Chart',
    component: Chart,
    meta: {
      keepAlive: true // 缓存
    }
  },
  {
    path: '/three',
    name: 'Three',
    component: Three,
    meta: {
      keepAlive: true // 缓存
    }
  }
]

然后在App.vue中使用标签包裹

<template>
  <div id="app">
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

最后,在路由切换时,根据meta属性控制缓存行为

const router = createRouter({
  history: createWebHistory(),
  routes
})

router.beforeEach((to, from, next) => {
  if (to.name === 'Chart' && from.name === 'Three') {
    // 从Three到Chart,不清除缓存
    to.meta.keepAlive = true
  } else if (to.name === 'Chart' && from.name === 'Upload') {
    // 从Upload到Chart,不缓存
    to.meta.keepAlive = false
  }
  next()
})


希望采纳:
要实现这个功能,你可以使用 Vue.js 的组件通信和缓存管理。

首先,你需要将 chart 和 three 组件分别包装在一个 keep-alive 组件中,以便缓存它们。然后,在 upload 到 chart 的过程中,将 chart 组件从 keep-alive 中移除,这样 chart 就不会被缓存。当 chart 需要返回时,将 chart 组件添加回 keep-alive 中,这样它就可以从缓存中获取。

<template>  
  <div>  
    <keep-alive>  
      <chart v-if="showChart" />  
    </keep-alive>  
    <three v-else />  
    <button @click="uploadToChart">Upload to Chart</button>  
  </div>  
</template>  
  
<script>  
export default {  
  data() {  
    return {  
      showChart: true,  
      chartData: "",  
    };  
  },  
  methods: {  
    async uploadToChart() {  
      // 这里是上传数据到 chart 的代码  
      // ...  
      // 在上传数据的过程中,将 chart 组件从 keep-alive 中移除  
      this.showChart = false;  
      // 等待上传完成后再将 chart 组件添加回 keep-alive 中  
      this.$nextTick(() => {  
        this.showChart = true;  
      });  
    },  
  },  
};  
</script>

在上面的代码中,当 showChart 为 true 时,会渲染 chart 组件;当 showChart 为 false 时,会渲染 three 组件。在 uploadToChart 方法中,将 showChart 设置为 false,这样 chart 组件就会被从 keep-alive 中移除。然后等待上传完成后再将 showChart 设置为 true,这样 chart 组件就会被添加回 keep-alive 中。这样就能实现 chart 不缓存,上传时 chart 不被缓存,返回时从缓存获取的效果。

可以借鉴下

// useCache.ts
import { ref } from "vue";

const KEEP_ALIVE_SET = ref(new Set([]));

export default () => {const setKeepAlive = <T extends "add" | "delete">( operate: T,value: number ) => {KEEP_ALIVE_SET.value[operate](value);};return {KEEP_ALIVE_SET,setKeepAlive};
}; 


答案参考ChatGPT Plus版,整理汇总。希望能帮助你解决问题
要实现在chart到three返回时,chart页面不刷新且缓存保持,而在upload到chart时,chart页面不缓存,可以按照以下步骤进行修改:

  1. 首先,在路由配置文件(router.ts)中,将chart路由的meta中的keepAlive设置为一个动态值,而不是固定的true。这样可以根据需要在不同情况下动态地开启或关闭缓存。修改后的代码如下:
{
  path: '/chart',
  name: 'chart',
  component: () => import('@/views/ChartView.vue'),
  meta: {
    keepAlive: this.$route.meta.chartKeepAlive  // 使用动态的keepAlive值
  }
}
  1. 在App.vue文件中,添加一个computed属性,根据当前路由名称来设置chartKeepAlive的值。修改后的代码如下:
<template>
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component
        :is="Component"
        v-if="$route.meta.keepAlive"
        :key="$route.name"
      ></component>
    </keep-alive>
    <component
      :is="Component"
      v-if="!$route.meta.keepAlive"
      :key="$route.name"
    ></component>
  </router-view>
</template>

<script>
import { defineComponent, ref } from "vue";

export default defineComponent({
  name: "App",
  setup() {
    const chartKeepAlive = ref(true);  // 初始值为true,表示chart页面缓存

    return {
      chartKeepAlive,
    };
  },
  computed: {
    routeMeta() {
      if (this.$route.name === "chart") {
        return { keepAlive: this.chartKeepAlive };  // 动态设置keepAlive
      } else {
        return this.$route.meta;
      }
    },
  },
});
</script>

<style scoped>
</style>
  1. 在上传页面(UploadView.vue)中,通过监听路由离开事件,在跳转到chart页面时将chartKeepAlive的值设置为false,表示不缓存chart页面。修改后的代码如下:
<script>
import { onBeforeRouteLeave } from "vue";

export default {
  name: "UploadView",
  setup() {
    onBeforeRouteLeave((to, from, next) => {
      if (to.name === "chart") {
        this.$root.chartKeepAlive = false;  // 在跳转到chart页面时关闭缓存
      }
      next();
    });

    return {};
  },
};
</script>

现在,当从upload页面跳转到chart页面时,chart页面将不会被缓存。而在chart页面跳转到three页面并返回时,chart页面将保持缓存,且不会刷新。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
你可以使用 beforeRouteLeave 路由守卫来动态更改 meta.keepAlive 属性。具体来说,只需要在 ChartView.vue 组件中添加以下代码即可:

beforeRouteLeave(to, from, next) {
  if (from.name === 'three') {
    this.$route.meta.keepAlive = true; // 在返回到 ChartView 时缓存
  }
  next();
}

App.vue 中,你可以根据路由的 meta 属性来判断是否缓存组件。以下是具体代码:

<template>
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component
        :is="Component"
        v-if="$route.meta.keepAlive || cachedViews.includes($route.name)"
        :key="$route.name"
      ></component>
    </keep-alive>
    <component
      :is="Component"
      v-if="!$route.meta.keepAlive && !cachedViews.includes($route.name)"
      :key="$route.name"
    ></component>
  </router-view>
</template>

<script>
import { ref } from 'vue';

export default {
  name: 'App',
  setup() {
    const cachedViews = ref([]);

    return {
      cachedViews
    };
  },
  watch: {
    $route(to, from) {
      if (from.name === 'chart' && to.name === 'three') {
        this.cachedViews.push('chart'); // 在进入 ThreeView 时不缓存 ChartView
      }
      if (to.name === 'chart' && from.name === 'upload') {
        this.cachedViews = this.cachedViews.filter(v => v !== 'chart'); // 在进入 ChartView 时清除缓存
      }
    }
  }
};
</script>

在这个例子中,cachedViews 数组是用来记录哪些页面被缓存的。在进入 ThreeView 组件时将 cachedViews 中的 chart 移除,这样在返回到 ChartView 组件时不会缓存。同时,在进入 ChartView 组件时清空 cachedViews 数组,这样记得到该组件中将不会缓存。
如果我的回答解决了您的问题,请采纳!

发送请求获取数据以后重新定义Echarts的series中的data值或者value值。

<template>
  <div class="lineargraph">
    <div id="bug"></div>
  </div>
</template>
 
<script>
import * as echarts from "echarts";
import { thirdAxios } from "../../../api/BackstageApi";
export default {
  mounted () {
    this.change()
  },
  methods: {
    change(){
      var myChart = echarts.init(document.getElementById("bug"));
      myChart.setOption({
        title: {
          text: "用户增长分布图",
          left: "20px",
          top: "18px",
          // 标题样式
          textStyle: {
            fontSize: 20,
            fontWeigth: 600,
            color: "black"
          }
        },
        tooltip: {
          trigger: "axis"
        },
        legend: {
          data: ["新增用户", "活跃用户", "临时停车用户"],
          top: "12%",
          right: "30%"
        },
        // 整个折线图位置调整
        grid: {
          top: "20%",
          left: "3%",
          right: "4%",
          bottom: "3%",
          containLabel: true
        },
        // x轴的刻度及x轴的显示
        xAxis: {
          axisTick: {
            show: false
          },
          axisLine: {
            show: false
          },
          type: "category",
          boundaryGap: false,
          data: [
            "1日",
            "3日",
            "6日",
            "9日",
            "12日",
            "15日",
            "18日",
            "21日",
            "24日",
            "27日",
            "30日"
          ],
          // 背景网格图
          splitLine: {
            show: true,
            lineStyle: {
              type: "dashed",
              color: "#cfcfcf"
            }
          }
        },
          // 背景网格图
        yAxis: {
          type: "value",
          splitLine: {
            show: true,
            lineStyle: {
              type: "dashed",
              color: "#cfcfcf"
            }
          }
        },
        series: [
          {
            name: "新增用户",
            symbol: "none",
            type: "line",
            smooth: true,
            data: [],
            // data:this.num1,
            itemStyle: {
              normal: {
                lineStyle: {
                  width: 10, // 设置线宽
                  type: "solid", //'dotted'虚线 'solid'实线
                  color: {
                    type: "radio", 
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 0,
                    colorStops: [
                      {
                        offset: 0,
                        color: "transparent" // 0% 处的颜色
                      },
                      {
                        offset: 0.4,
                        color: "#5034fe" // 100% 处的颜色
                      },
                      {
                        offset: 0.6,
                        color: "#8ac8ff" // 100% 处的颜色
                      },
                      {
                        offset: 1,
                        color: "transparent" // 100% 处的颜色
                      }
                    ],
                    globalCoord: false // 缺省为 false
                  }
                }
              }
            }
          },
          {
            name: "活跃用户",
            type: "line",
            smooth: true,
            data: [],
            // data:this.num2,
            itemStyle: {
              normal: {
                lineStyle: {
                  width: 10, // 设置线宽
                  type: "solid", //'dotted'虚线 'solid'实线
                  color: {
                    type: "radio",
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 0,
                    colorStops: [
                      {
                        offset: 0,
                        color: "transparent" // 0% 处的颜色
                      },
                      {
                        offset: 0.4,
                        color: "green" // 100% 处的颜色
                      },
                      {
                        offset: 0.6,
                        color: "red" // 100% 处的颜色
                      },
                      {
                        offset: 1,
                        color: "transparent" // 100% 处的颜色
                      }
                    ],
                    globalCoord: false // 缺省为 false
                  }
                }
              }
            }
          },
          {
            name: "临时停车用户",
            smooth: true,
            type: "line",
 
            data: [],
            // data:this.num3,
            itemStyle: {
              normal: {
                lineStyle: {
                  width: 10, // 设置线宽
                  type: "solid", //'dotted'虚线 'solid'实线
                  color: {
                    type: "radio",
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 0,
                    colorStops: [
                      {
                        offset: 0,
                        color: "transparent" // 0% 处的颜色
                      },
                      {
                        offset: 0.4,
                        color: "#fd972e" // 100% 处的颜色
                      },
                      {
                        offset: 0.6,
                        color: "#f6bc6b" // 100% 处的颜色
                      },
                      {
                        offset: 1,
                        color: "transparent" // 100% 处的颜色
                      }
                    ],
                    globalCoord: false // 缺省为 false
                  }
                }
              }
            }
          }
        ]
 
      })  
// option结束
 
 
thirdAxios().then( res =>{
 
if(res.code == 200){
  
let arr1 = res.data.num1;
let arr2 = res.data.num2;
let arr3 = res.data.num3;
// console.log(arr1,arr2,arr3);
 
myChart.setOption({
  series: [
          {
            name: "新增用户",
            symbol: "none",
            type: "line",
            smooth: true,
            data: arr1,
            // data:this.num1,
            itemStyle: {
              normal: {
                lineStyle: {
                  width: 10, // 设置线宽
                  type: "solid", //'dotted'虚线 'solid'实线
                  color: {
                    type: "radio",
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 0,
                    colorStops: [
                      {
                        offset: 0,
                        color: "transparent" // 0% 处的颜色
                      },
                      {
                        offset: 0.4,
                        color: "#5034fe" // 100% 处的颜色
                      },
                      {
                        offset: 0.6,
                        color: "#8ac8ff" // 100% 处的颜色
                      },
                      {
                        offset: 1,
                        color: "transparent" // 100% 处的颜色
                      }
                    ],
                    globalCoord: false // 缺省为 false
                  }
                }
              }
            }
          },
          {
            name: "活跃用户",
            type: "line",
            symbol: "none",
            smooth: true,
            data: arr2,
            // data:this.num2,
            itemStyle: {
              normal: {
                lineStyle: {
                  width: 10, // 设置线宽
                  type: "solid", //'dotted'虚线 'solid'实线
                  color: {
                    type: "radio",
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 0,
                    colorStops: [
                      {
                        offset: 0,
                        color: "transparent" // 0% 处的颜色
                      },
                      {
                        offset: 0.4,
                        color: "#8cc265" // 100% 处的颜色
                      },
                      {
                        offset: 0.6,
                        color: "#6bdb20" // 100% 处的颜色
                      },
                      {
                        offset: 1,
                        color: "transparent" // 100% 处的颜色
                      }
                    ],
                    globalCoord: false // 缺省为 false
                  }
                }
              }
            }
          },
          {
            name: "临时停车用户",
            smooth: true,
            type: "line",
            symbol: "none",
            data: arr3,
            // data:this.num3,
            itemStyle: {
              normal: {
                lineStyle: {
                  width: 10, // 设置线宽
                  type: "solid", //'dotted'虚线 'solid'实线
                  color: {
                    type: "radio",
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 0,
                    colorStops: [
                      {
                        offset: 0,
                        color: "transparent" // 0% 处的颜色
                      },
                      {
                        offset: 0.4,
                        color: "#fd972e" // 100% 处的颜色
                      },
                      {
                        offset: 0.6,
                        color: "#f6bc6b" // 100% 处的颜色
                      },
                      {
                        offset: 1,
                        color: "transparent" // 100% 处的颜色
                      }
                    ],
                    globalCoord: false // 缺省为 false
                  }
                }
              }
            }
          }
        ]
})
 
}
} )
      
    }
  }
 
}
</script>
<style lang="less" scoped>
.lineargraph {
  height: 400px;
  width: 100%;
  margin-top: 20px;
  border-radius: 10px;
  box-shadow: 1px 1px 3px 0 #848b7f;
    background: white;
 
  #bug{
    width: 100%;
    height: 100%;
    // background: red;
  }
}
</style>