likes
comments
collection
share

vue3动态组件及组件缓存的使用(setup函数和setup语法糖两版)

作者站长头像
站长
· 阅读数 55

一、动态组件

  • 动态组件可通过v-if或v-show控制显示隐藏,在此不做演示;
  • 动态组件可通过component标签中的is属性控制;
  • 具体写法:<component :is="组件名"></component>

常规写法

<template>
  <div class="box">
      <leOne></leOne>
      <leTwo></leTwo>
  </div>
</template>
<script setup>
// 引入组件
import leOne from "@/components/leOne.vue";
import leTwo from "@/components/leTwo.vue";
</script>
<style scoped lang="scss"></style>

使用动态组件

<template>
  <div class="box">
        <component :is="leOne"></component>
        <component :is="leTwo"></component>
  </div>
</template>
<script setup>
// 引入组件
import leOne from "@/components/leOne.vue";
import leTwo from "@/components/leTwo.vue";
</script>
<style scoped lang="scss"></style>

动态组件进阶写法

  • setup函数版本
<template>
  <div class="box">
    <div class="tab">
      // 通过事件控制组件名称,是否创建组件
      <div v-for="item, index in units" 
          @click="changeTap(index)" 
          :class="{ activeBgc: i == index }">
          切换{{ item }}
       </div>
    </div>
    <component :is="units[i]"></component>
  </div>
</template>
<script>
// 引入
import { reactive, toRefs } from 'vue';
// 引入组件
import leOne from "@/components/leOne.vue";
import leTwo from "@/components/leTwo.vue";
export default {
  name: 'AboutView',
  // 注册组件
  components: {
    leOne,
    leTwo
  },
  setup() {
    const data = reactive({
      units: ['leOne', 'leTwo'],
      i: 0
    })
    // tap变动
    function changeTap(index) {
      data.i = index
    }
    return {
      ...toRefs(data),
      changeTap
    }
  },
}
</script>
<style scoped lang="scss">
.activeBgc {
  background-color: pink;
}
</style>
  • setup语法糖版本
  • 通过markRaw()实现动态渲染组件
<template>
  <div class="box">
    <div class="tab">
      <div v-for="item, index in units" 
          @click="changeTap(index)" 
          :class="{ activeBgc: i == index }">
          切换{{ item.name }}
      </div>
    </div>
    <component :is="units[i].comName"></component>
  </div>
</template>
<script setup>
// 引入
import { reactive, toRefs, markRaw } from 'vue';
// 引入组件
import leOne from "@/components/leOne.vue";
import leTwo from "@/components/leTwo.vue";
// markRaw()标记一个对象,使其永远不会再成为响应式对象
// 在动态渲染组件的时候我们就可以使用 markRaw 包裹。
const data = reactive({
  units: [
    {
      name: "leOne",
      comName: markRaw(leOne)
    },
    {
      name: "leTwo",
      comName: markRaw(leTwo)
    }
  ],
  i: 0
})
// tap变动
function changeTap(index) {
  data.i = index
}
// 解构数据
const { units, i } = toRefs(data)
</script>
<style scoped lang="scss">
.activeBgc {
  background-color: pink;
}
</style>

二、缓存组件

  • keep-alive是vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM;
  • keep-alive有以下几个属性:

1、 include: 只有名称匹配的组件会被缓存 (支持字符串或正则表达); 2、 exclude: 任何名称匹配的组件都不会被缓存(支持字符串或正则表达); 3、 max:最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁

include和exclude

<KeepAlive> 默认会缓存内部的所有组件实例,但我们可以通过 include 和 exclude来定制该行为。这两个属性的值可以是一个以英文逗号分隔的字符串或一个正则表达式,或是包含这两种类型的一个数组:

<!-- 以英文逗号分隔的字符串 -->
<keep-alive include="leOne,leTwo">
      <component :is="units[i].comName"></component>
</keep-alive>
<!-- 正则表达式 (需使用 `v-bind`) -->
<keep-alive :include="/leOne|leTwo/">
      <component :is="units[i].comName"></component>
</keep-alive>
<!-- 数组 (需使用 `v-bind`) --> 
<KeepAlive :include="['leOne', 'leTwo']"> 
    <component :is="units[i].comName" /> 
</KeepAlive>
  • 注意:
  • 它会根据组件的name选项进行匹配,所以组件如果想要条件性地被 KeepAlive 缓存,就必须显式声明一个 name 选项
  • 使用 <script setup> 的单文件组件会自动根据文件名生成对应的 name 选项,无需再手动声明

max

  • 可以通过传入 max来限制可被缓存的最大组件实例数。
  • <KeepAlive>在指定了 max 后类似一个 LRU 缓存:如果缓存的实例数量即将超过指定的那个最大数量,则最久没有被访问的缓存实例将被销毁,以便为新的实例腾出空间。
<KeepAlive :max="10"> 
    <component :is="units[i].comName" /> 
</KeepAlive>

缓存组件的生命周期

  • 使用keep-alive会增加两个生命周期函数,分别是:onActivated / onDeactivated
  • onActivated 在组件挂载时会被调用,
  • onDeactivated在组件卸载时会被调用。
  • 这两个钩子不仅适用于 <KeepAlive> 缓存的根组件,也适用于缓存树中的后代组件。
<template>
    <KeepAlive> 
       <component :is="units[i].comName" /> 
    </KeepAlive>
</template>
<script setup>
  import { ref,onActivated,onDeactivated, onMounted, onUnmounted } from 'vue'
  onMounted(() => {
    console.log("初始化")
  })
  onActivated(() => {
    console.log("keepAlive 初始化")
  })
  onDeactivated(() => {
    console.log("keepAlive 销毁")
  })
  onUnmounted(() => {
    console.log("销毁")
  })
</script>
<style scoped></style>
转载自:https://juejin.cn/post/7246638858912448569
评论
请登录