vue3使用keep-alive组件,包含动态组件使用

news2024/11/14 21:26:33

vue3使用keep-alive组件,包含动态组件使用

本文目录

    • vue3使用keep-alive组件,包含动态组件使用
      • 组件不使用keep-alive
      • 组件中使用
        • v-if切换
        • component动态组件切换
          • 因注释导致的意外错误
          • 动态组件的使用
          • 完整示例
      • 路由不使用keep-alive
      • 路由中使用
      • keep-alive生命周期

组件不使用keep-alive

  • Father
<template>
  <div>
    Father
    <el-button @click="tabChange">change page</el-button>
    <Child :msg="cutTab" v-if="cutTab"></Child>
    <Child2 :msg="cutTab" v-else></Child2>
  </div>
</template>

<script setup lang="ts" name="Father">
const cutTab = ref(false);

const tabChange = () => {
  cutTab.value = !cutTab.value;
}
</script>
  • Child
<template>
  <div class="c1">
    Child +
    {{ props.msg }}
    <el-input v-model="input" placeholder="Please input" />
  </div>
</template>

<script setup lang="ts" name="Child">
const props = defineProps({
  msg: {
    type: Boolean,
    default: false,
  },
})
const input = ref('')
</script>
  • Child2
<template>
  <div class="c2">
    Child2 +
    {{ props.msg }}
    <el-input v-model="input" placeholder="Please input" />
  </div>
</template>

<script setup lang="ts" name="Child2">
const props = defineProps({
  msg: {
    type: Boolean,
    default: false,
  },
})
const input = ref('')
</script>

组件中使用

  • include:包含
  • exclude:排除

v-if切换

    <keep-alive>
      <Child :msg="cutTab" v-if="cutTab"></Child>
      <Child2 :msg="cutTab" v-else></Child2>
    </keep-alive>
    <keep-alive include="Child2">
      <Child :msg="cutTab" v-if="cutTab"></Child>
      <Child2 :msg="cutTab" v-else></Child2>
    </keep-alive>

component动态组件切换

因注释导致的意外错误
  • <KeepAlive> expects exactly one child component
    <keep-alive include="Child2">
      <!-- <Child :msg="cutTab" v-if="cutTab"></Child>
      <Child2 :msg="cutTab" v-else></Child2> -->
      <component :is="com"></component>
    </keep-alive>

keep-alive组件内不要使用注释,会被解析为子节点

  • 添加div进行包裹
    <keep-alive include="Child2">
      <div>
        <!-- <Child :msg="cutTab" v-if="cutTab"></Child>
        <Child2 :msg="cutTab" v-else></Child2> -->
        <component :is="com"></component>s
      </div>
    </keep-alive>
  • 移除注释
    <keep-alive include="Child2">
      <component :is="com"></component>
    </keep-alive>
动态组件的使用

[Vue warn]: Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with 'markRaw' or using 'shallowRef' instead of 'ref'.

在 Vue 3 中,如果用 ref 或 reactive 将一个组件包装成响应式对象,可能会引发不必要的性能开销。因为这会使 Vue 尝试去追踪组件的变化,而实际上组件实例并不需要被追踪。组件本身不应该是响应式的,只有它的 props 和 state 才应该是响应式的。

所以,当需要引用一个组件时,应该使用 shallowRef或者 markRaw,这样可以避免将整个组件变成响应式的,只会跟踪引用的变化

  • 使用markRaw
const com = ref(markRaw(Child2));

const comChange = () => {
  if(com.value === Child2){
    com.value = markRaw(Child);
  }else{
    com.value = markRaw(Child2);
  }
}
  • 使用shallowRef
const com = shallowRef(Child2);

const comChange = () => {
  if(com.value === Child2){
    com.value = Child;
  }else{
    com.value = Child2;
  }
}
完整示例
<template>
  <div>
    Father
    <el-button @click="comChange">change component</el-button>
    <keep-alive include="Child2">
      <component :is="com"></component>
    </keep-alive>
  </div>
</template>

<script setup lang="ts" name="Father">
import Child from "@/views/Child.vue";
import Child2 from "@/views/Child2.vue";

const cutTab = ref(false);
const com = ref(markRaw(Child2));

const comChange = () => {
  if(com.value === Child2){
    com.value = markRaw(Child);
  }else{
    com.value = markRaw(Child2);
  }
}

</script>

可以看到只有Child2组件是有缓存的,Child是有销毁和生成的

路由不使用keep-alive

  • 组件
<template>
  <div>
    Father
    <div class="nav">
      <router-link to="/Father/Child">去Child页面</router-link>
      <el-divider direction="vertical" />
      <router-link to="/Father/Child2">去Child2页面</router-link>
    </div>
    <router-view></router-view>
  </div>
</template>
  • 路由index.ts
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'

const routes = [
  {
    path: '/Father',
    name: 'Father',
    component: () => import('@/views/Father.vue'),
    children: [
      {
        path: 'Child',
        name: 'Child',
        component: () => import('@/views/Child.vue'),
      },
      {
        path: 'Child2',
        name: 'Child2',
        component: () => import('@/views/Child2.vue'),
      }
    ],
  }, 
]

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

export default router

路由中使用

  • Vue Router 4(与 Vue 3 配套的路由库)引入了一个新的 API 来实现路由级别的 <keep-alive>。这就是 <router-view> 组件的 v-slot API

    • 需要注意的是v-if不要加在keep-alive上,会直接销毁keep-alive,需要加在component
    • 实现页面部分刷新,页面进入时执行的生命周期为:created->mounted->activated
<template>
  <div>
    Father
    <div class="nav">
      <router-link to="/Father/Child">去Child页面</router-link>
      <el-divider direction="vertical" />
      <router-link to="/Father/Child2">去Child2页面</router-link>
    </div>
    <router-view v-slot="{ Component }">
      <keep-alive >
        <component :is="Component" v-if="$route.meta.keepAlive"/>
      </keep-alive>
      <component :is="Component" v-if="!$route.meta.keepAlive"/>
    </router-view>
  </div>
</template>
  • 路由index.ts

    • 在对应的路由上添加meta属性来设置页面是否要使用缓存
...
const routes = [
  {
    path: '/Father',
    name: 'Father',
    component: () => import('@/views/Father.vue'),
    children: [
      {
        path: 'Child',
        name: 'Child',
        component: () => import('@/views/Child.vue'),
      },
      {
        path: 'Child2',
        name: 'Child2',
        meta: {
          keepAlive: true,  // 需要被keep-alive
        },
        component: () => import('@/views/Child2.vue'),
      }
    ],
  }, 
]
...

keep-alive生命周期

keep-alive组件会多出两个生命周期,分别在mounted之后和unMounted之前

onActivated(() => {
  console.log('Component is activated')
})

onDeactivated(() => {
  console.log('Component is deactivated')
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/510305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

公司数字化转型,如何选择高效的知识管理工具?

随着企业数字化转型的加速&#xff0c;知识管理工具的重要性也日益凸显。好的知识管理工具可以帮助企业提高工作效率、降低成本、提高创新能力和竞争力。但是&#xff0c;市场上的知识管理工具繁多&#xff0c;如何选择高效的知识管理工具成为了企业面临的一大难题。本文将从以…

Jenkins 入门系列之Role-based Strategy配置Gitlab Group管理用户组

目录 背景步骤1. 安装插件2. 配置Gitlab Group3. 配置 Jenkins 授权策略4. 配置 Jenkins 角色与授权5. 验证 背景 版本 Jenkins Version&#xff1a;Jenkins 2.403Gitlab Version: Gitlab 15.6部署环境&#xff1a;群晖NAS Docker 部署JenkinsGitlab 上一篇文章Jenkins 入门…

HTML详解

HTML是什么 html是一门语言&#xff0c;所有的网页都是用它编写出来的。 他是一门超文本标记语言。可以定义图片&#xff0c;音频&#xff0c;视频等。由标签组成。 HTMl仅仅定义了网站的接口。 具体的表现还需要css来实现&#xff0c;也就是css让网页变得更加好看。 网页…

智能聊天机器人ChatGPT商业版

作为一个智能聊天机器人&#xff0c;我是由OpenAI开发的。目前&#xff0c;我的商业版需要通过OpenAI的合作伙伴计划进行许可和部署&#xff0c;以确保我被用于适当的商业用途。如果您对商业使用感兴趣&#xff0c;请联系OpenAI以获取更多信息。 智能聊天机器人是一种能够自…

如何优化golang gc

目录 一.理解GO GC机制 1.1GC的耗时 1.2堆大小对GC的影响 1.3GC算法 二 如何查看GC信息 2.1使用GODEBUG"gotrace1" 2.2 go tool trace 2.3 debug.ReadGCStats ​编辑2.4 runtime.ReadMemStats 三 GC优化技巧 2.1并发GC 一.理解GO GC机制 GO语言采用的是三…

学习网络安全的拦路虎!你遇到几个?

很多零基础的同学想要学习网络安全&#xff0c;前期会各种寻找学习资料。最后发现资料一大堆&#xff0c;但无从下手&#xff0c;于是千辛万苦收集的资料就去收藏夹吃灰了。开始学习的小伙伴们通常也会越学越迷茫&#xff0c;毕竟资料并不是完整的&#xff0c;而是东拼西凑出来…

Docker时区问题

背景 当前docker容器技术应用越来越广泛&#xff0c;但在启动容器后&#xff0c;容器内部的时间并不是东八区 Docker的基础镜像设置大多是UTC&#xff0c;也就是标准的UTC 时间&#xff0c;所以要简单的调整一下&#xff0c;变成中国标准时间CST(China Standard Time UTC8:0…

OpenCL编程指南-1.2OpenCL图形API

OpenCL与图形 OpenCL的出现是对GPCPU编程的一个响应。人们用GPU处理图形&#xff0c;并且开始使用GPU完成工作中的非图形部分。基于这种趋势&#xff0c;异构计算&#xff08;已经存在很长时间&#xff09;与图形发生冲突&#xff0c;因此迫切需要一个行业标准。 OpenCL一直与…

使用Onenote进行钓鱼攻击事件分析

以其中遇到的一个案例为例子进行展开分析: 1、使用钓鱼邮件文案.one文件附件 From: Bank Complaints <bankcomplaintshkmagov.com> Sent: Thursday, March 2, 2023 11:00 AMTo: Miles Mok XXXXSubject: [External Mail] xxxx Industry Development Survey Dear XXXX Lt…

SpringBoot+Canal+RabbitMQ实战

1. Canal简介 https://github.com/alibaba/canal 1.1 Canal工作原理 MySQL主备复制原理 MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events&#xff0c;可以通过 show binlog events 进行查看)MySQL slave 将 master 的 b…

中断-NVIC与EXTI外设详解(超全面)

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;玩转STM32 &#x1f4ac;推荐一…

档案馆对于档案室档案库房内温度和湿度的控制要求

编辑搜图 请点击输入图片描述&#xff08;最多18字&#xff09; 01 纸质档案库的温湿度要求 用房名称温度&#xff08;℃&#xff09;相对湿度&#xff08;%&#xff09;纸质档案库14~2445~60 02 特殊档案库的温湿度要求 用房名称温度&#xff08;℃&#xff09;相对湿度&am…

Golang中的运算符

目录 运算符 算术运算符 代码案例&#xff1a; 关系运算符 代码案例&#xff1a; 逻辑运算符 代码案例&#xff1a; 位运算符 代码案例&#xff1a; 赋值运算符 代码案例&#xff1a; 其他运算符 运算符 算术运算符 Go语言中的算术运算符包括加、减、乘、除和取模…

【深入理解redis】数据结构

文章目录 动态字符串SDS字符串编码类型 intsetDictZipListZipList的连锁更新问题 QuickListSkipListRedisObjectStringListSet结构ZSETHash Redis 共有 5 种基本数据结构&#xff1a;String&#xff08;字符串&#xff09;、List&#xff08;列表&#xff09;、Set&#xff08;…

2023进销存财务软件哪个好?哪些适合中小商户使用?

对于开店的老板来说&#xff0c;门店的财务管理一直都是比较头疼的一件事&#xff0c;销售业绩人工统计困难&#xff0c;记账对账效率低且容易出错。 使用进销存财务软件可以有效的帮助门店解决财务管理问题&#xff0c;但市面上这么多进销存财务软件&#xff0c;哪些性价比较高…

Android编译优化之混淆配置

Android编译优化之混淆配置 背景 为了使用java8及后续java新版本的特性&#xff0c;Google增加了一步编译过程—脱糖&#xff08;desugaring&#xff09;&#xff0c;但这一步会导致更长的编译时间&#xff0c;这也是为什么Google会推出D8和R8编译器来优化编译速度。 什么是脱…

【C语言】扫雷游戏

这里写目录标题 前言1.初始化棋盘2.展示棋盘3.布置雷4.开始扫雷4.1判断输赢4.2扫雷时连续性展开4.3展示玩法 5.整体代码展示5.1 game.h头文件展示5.2 game.c源文件展示5.3 text.c源文件展示 所属专栏&#xff1a;C语言 博主首页&#xff1a;初阳785 代码托管&#xff1a;chuyan…

了解 XML结构(一)

文章目录 1 XML定义2 了解XML结构3 XML节点类型4 加载读取XML5 小结 1 XML定义 XML是一种可扩展标记语言&#xff08;Extensible Markup Language, XML&#xff09;,可以用来标记数据&#xff0c;定义数据类型&#xff0c;是一种允许用户对自己的标记语言进行定义的源语言。 …

数据治理是一个部门的工作还是全业务体系的工作?_光点科技

随着互联网时代的到来&#xff0c;数据已成为企业生产和经营的重要资源。但是&#xff0c;随着数据量的不断增加和数据形态的多样化&#xff0c;如何管理和利用数据也成为了企业面临的一个重要问题。在这个过程中&#xff0c;数据治理成为了一个备受关注的话题。 那么&#xff…

ChatGPT1论文解读《Improving Language Understanding by Generative Pre-Training》

论文总结 以下是我阅读完整篇论文做的个人总结&#xff0c;基本包含了chatGPT1设计的完整框架思路&#xff0c;可以仅看【论文总结】章节。 在GPT1实现的核心架构中&#xff0c;包含两个阶段。 第一阶段 在第一阶段基于一个包含7000本书籍内容的海量未标注文本数据集进行无…