- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
在 vue 中,默认情况下,一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态——当这个组件再一次被显示时,会创建一个只带有初始状态的新实例。但是 vue 提供了 keep-alive 组件,它可以将一个动态组件包装起来从而实现组件切换时候保留其状态。本篇文章要介绍的并不是它的基本使用方法(这些官网文档已经写的很清楚了),而是它如何结合 VueRouter 来更自由的控制页面状态的缓存 。
我们先搭建一个 Vue 项目,里面有三个页面 a , b , c ,并给它们一些相互跳转的逻辑和状态 。
<template>
<div>
<div>A页面</div>
<input type="text" v-model="dataA" /><br />
<div @click="toB">跳转B</div>
<div @click="toC">跳转C</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { useRouter, useRoute } from "vue-router";
const router = useRouter();
const route = useRoute();
const dataA = ref("");
const toB = () => {
router.push("/bb");
};
const toC = () => {
router.push("/cc");
};
</script>
<template>
<div>
<div>B页面</div>
<input type="text" v-model="dataB" /><br />
<div @click="toA">跳转A</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
const dataB = ref("");
const toA = () => {
router.push("/aa");
};
</script>
<template>
<div>
<div>C页面</div>
<input type="text" v-model="dataC" />
<div @click="toA">跳转A</div>
</div>
</template>
<script lang="ts" setup name="C">
import { ref } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
const dataC = ref("");
const toA = () => {
router.push("/aa");
};
</script>
然后在 route/index.ts 写下它们对应的路由配置 。
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
const routes: RouteRecordRaw[] = [
{
path: "/aa",
name: "a",
component: () => import(/* webpackChunkName: "A" */ "../views/a.vue"),
},
{
path: "/bb",
name: "b",
component: () => import(/* webpackChunkName: "B" */ "../views/b.vue"),
},
{
path: "/cc",
name: "c",
component: () => import(/* webpackChunkName: "C" */ "../views/c.vue"),
},
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
在 App.vue 中我们用 keep-alive 将 router-view 进行包裹 。
<template>
<keep-alive>
<router-view />
</keep-alive>
</template>
启动项目,测试一下页面状态有没有被缓存 。
此时我们发现状态并没有缓存,并且控制台还给了个警告 。
上面的写法在 vue2 中是可以的,但是在 vue3 中需要将 keep-alive 写在 router-view 中才行,我们修改一下写法 。
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</template>
这种写法其实就是 router-view 组件的插槽传递了一个带有当前组件的组件名 Component 的对象,然后用 keep-alive 包裹一个动态组件(回归原始写法).
我们再试一下页面的缓存效果,这时候发现页面的状态被缓存了 。
通常情况下我们并不想将所有页面状态都缓存,而只想缓存部分页面,这样的话该怎么做呢?
其实我们可以在 template 中通过$route 获取路由的信息,所以我们可以在需要缓存的页面配置一下 meta 对象,比如 a 页面我们想缓存其状态,可以将 keepAlive 设置位 true 。
//route/index.ts
const routes: RouteRecordRaw[] = [
{
path: "/aa",
name: "a",
meta: {
keepAlive: true,
},
component: () => import(/* webpackChunkName: "A" */ "../views/a.vue"),
},
...
];
然后回到 App.vue 中判断 keepAlive 来决定是否缓存 。
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component v-if="$route.meta.keepAlive" :is="Component" />
</keep-alive>
<component v-if="!$route.meta.keepAlive" :is="Component" />
</router-view>
</template>
再看下效果 。
此时我们发现 a 页面状态被缓存,b 页面的状态没有缓存 。
但是有时候我们想要这样一个效果 。
a 跳转 b 的时候我们需要缓存 a 页面状态,但是当 a 跳转 c 的时候我们不需要缓存 a 页面,此时我们该如何做呢?
或许有的同学想到了这样一个方法,当 a 跳转 c 的时候将 a 页面的缓存删除,这样就实现了上面的效果。可惜我找了半天也没找到 vue3 中删除指定页面缓存的方法 。
我也尝试过跳转 c 页面的时候将 a 的 keepAlive 设置为 false,但是再次回到 a 页面的时候 keepAlive 会重置,a 页面状态依然会被缓存.
既然如此为了做到更精细的缓存控制只有使用 keep-alive 中的 inclue 属性了 。
keep-alive 默认会缓存内部的所有组件实例,但我们可以通过 include 来定制该行为。它的值都可以是一个以英文逗号分隔的字符串、一个正则表达式,或是一个数组。这里我们使用一个数组来维护需要缓存的组件页面,注意这个数组中是组件的名字而不是路由的 name 。
在 vue3 中给组件命名可以这样写 。
<script lang='ts'>
export default {
name: 'MyComponent',
}
</script>
但是我们通常会使用 setup 语法,这样的话我们得写两个 script 标签,太麻烦。我们可以使用插件 vite-plugin-vue-setup-extend 处理 。
npm i vite-plugin-vue-setup-extend -D
然后在 vite.config.ts 中引入这个插件就可以使用了 。
import { defineConfig, Plugin } from "vite";
import vue from "@vitejs/plugin-vue";
import vueSetupExtend from "vite-plugin-vue-setup-extend";
export default defineConfig({
plugins: [vue(), vueSetupExtend()],
});
然后就可以这样命名了 。
<script lang="ts" setup name="A"></script>
下面我们修改一下 App.vue 。
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="['A']">
<component :is="Component" />
</keep-alive>
</router-view>
</template>
这其实就代表组件名为 A 的 页面才会被缓存,接下来我们要做的就是控制这个数组来决定页面的缓存,但是这个数组要放在哪里维护呢? 答案肯定是放到全局状态管理器中拉。所以我们引入 Pinia 作为全局状态管理器 。
npm i pinia
在 main.ts 中注册 。
import { createPinia } from "pinia";
const Pinia = createPinia();
createApp(App).use(route).use(Pinia).use(RouterViewKeepAlive).mount("#app");
新建 store/index.ts 。
import { defineStore } from "pinia";
export default defineStore("index", {
state: (): { cacheRouteList: string[] } => {
return {
cacheRouteList: [],
};
},
actions: {
//添加缓存组件
addCacheRoute(name: string) {
this.cacheRouteList.push(name);
},
//删除缓存组件
removeCacheRoute(name: string) {
for (let i = this.cacheRouteList.length - 1; i >= 0; i--) {
if (this.cacheRouteList[i] === name) {
this.cacheRouteList.splice(i, 1);
}
}
},
},
});
在 App.vue 中使用 cacheRouteList 。
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="catchStore.cacheRouteList">
<component :is="Component" />
</keep-alive>
</router-view>
</template>
<script lang="ts" setup>
import cache from "./store";
const catchStore = cache();
</script>
此时就可以根据 cacheRouteList 控制缓存页面了.
此时我们再来实现前面提到的问题 a 跳转 b 的时候我们需要缓存 a 页面状态,但是当 a 跳转 c 的时候我们不需要缓存 a 页面 就很简单了 。
import cache from "../store";
const catchStore = cache();
const router = useRouter();
const toB = () => {
catchStore.addCacheRoute("A");
router.push("/bb");
};
const toC = () => {
catchStore.removeCacheRoute("A");
router.push("/cc");
};
此时再看下页面的效果 。
可以发现 a 到 c 后再回来状态就重置了,这样不仅做到了上述效果,还可以让你随时随地的去删除指定组件的缓存.
到这里我们便完成了使用 inclue 对页面状态缓存进行更精细化的控制。当然,如果你有更好的方案欢迎在评论区指出,一起讨论探索 。
最后此篇关于Vue3中keepAlive如何搭配VueRouter来更自由的控制页面的状态缓存?的文章就讲到这里了,如果你想了解更多关于Vue3中keepAlive如何搭配VueRouter来更自由的控制页面的状态缓存?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
大家好,我完成了这个基本的 C 程序,它向输入任何给定数字集的用户显示有序集、最小值、最大值、平均值和中值。我遇到的问题是,当我打印数字时,我必须使用诸如“3.2%f”之类的东西来设置标准的精度,我怎
我有这个基于 Python 的服务守护进程,它正在执行大量多路复用 IO(选择)。 从另一个脚本(也是 Python)我想查询这个服务守护进程的状态/信息和/或控制处理(例如暂停它、关闭它、更改一些参
我读到 Fortran 对表达式求值的顺序有严格的规则。对于某些数值算法来说,这一点非常重要。 数值 C 程序如何控制浮点运算的顺序并防止编译器“优化”到不需要的运算顺序,例如将 (a*b)*c 更改
上下文: 整个问题可以概括为我正在尝试复制调用system(或fork)的行为,但在 mpi 环境中。 (事实证明,你不能并行调用system。)这意味着我有一个程序在许多节点上运行,每个节点上有一个
我考虑过控制scanf来接受c中的任何输入。我的概念是等待10秒(或任何其他时间)来接受任何输入。10秒后它将退出并且不再接收任何输入。 int main(){ int a,b,c,d; sca
我正在尝试使用生成器停止 setTimeOut 上的执行流程。我究竟做错了什么?我无法让 console.log 每 1500 毫秒退出一次。我是 node 的新手,如果我在做一件非常愚蠢的事情,请不
我希望我的应用程序的 Activity 堆栈包含同一 Activity 的多个实例,每个实例处理不同的数据。因此,我将让 Activity A 在我的 Activity 堆栈中处理数据 a、b、c 和
我有这个 bash 文件,它向设备询问 OpenSSH 的 IP、密码等。 现在,如果我使用 ssh root@ip,我必须输入密码。这真的很烦人。第二;我不能让我的脚本向它发送命令。 这就是我想要的
我正在尝试测试我有权访问的机器的缓存属性。为此,我正在尝试读取内存并对其计时。我改变工作集大小和步幅访问模式以获得不同的测量值。 代码如下所示: clock1 = get_ticks() for (i
我正在尝试编写一个 makefile 来替换用于构建相当大的应用程序的脚本之一。 当前脚本一次编译一个文件,使用 make 的主要原因是并行化构建过程。使用 make -j 16 我目前在办公室服务器
我正在制作一个小的测试程序,它演示了一个粗糙的控制台界面。 该程序是一个低于标准的典型获取行、响应程序,它甚至不识别“退出”,并希望您通过按 control-c 强制退出。在 Mingw32 上完成。
好的,我有一个 VOIP 电话。我知道电话的 IP 地址和端口,并且可以完全访问电话,我正在使用它通过 SIP 中继调用 SIP 电话。 我基本上想随时查看手机上发生的事情,但我不知道从哪里开始。 如
是否可以指定 CWinApp::WriteProfileString() 使用的应用程序名称? 如果我使用 CWinApp::SetRegistryKey 将我的公司名称设置为“MyCompany”,
我正在尝试用 Python 控制 Tor。我在 stackoverflow 上阅读了其他几个关于这个主题的问题,但没有一个能回答这个问题。 我正在寻找一种方法,以便在命令运行时为您提供“新身份”、新
最近在做一个项目,涉及到iPhone设备和手表传输数据、控制彼此界面跳转,在网上找了很多资料,发现国内的网站这方面介绍的不多,而国外的网站写的也不是很全,所以在这写这篇文章,给大家参考一下,望大神指
我想增加图中值的范围。在示例中,值的范围从 50 到 200。但是,我需要按如下方式分配值:50 75 100 125 150 175 200 并且最好使用 scale_fill_gradientn
我有一个IconButton,当按下时波纹效果是圆形的并且比按钮的面积大,我怎样才能减少点击按钮时波纹效果的大小? IconButton( constraints
我正在使用代码契约(Contract)为我的项目生成附属程序集。基本上它为项目的 MyAssembly.dll 创建一个 MyAssembly.Contracts.dll。这应该放在你的程序集旁边,但
我想使用分面绘制图形,其中面板之间的边缘不同。面板按字母顺序自动排序(按照 ggplot 中的惯例)。一个简单的例子: library(igraph) library(ggraph) g <- mak
我想为我的 Android 应用程序创建一个小部件,以显示有关位置的一些实时详细信息,例如天气。但我想在任何时候允许最多 3 个小部件实例,每个实例都有不同的位置。我不确定该怎么做,也找不到任何信息。
我是一名优秀的程序员,十分优秀!