Vue3中的动态组件详解

 更新时间:2025年02月24日 09:07:19   作者:秀秀_heo  
本文介绍了Vue3中的动态组件,通过`<component :is="动态组件名或组件对象"></component>`来实现根据条件动态渲染不同的组件,此外,还提到了使用`markRaw`和`shallowRef`来优化性能,避免不必要的响应式劫持

Vue3动态组件

动态组件的基本使用

动态组件(Dynamic Components)是一种在 Vue 中根据条件或用户输入来动态渲染不同组件的技术。

在 Vue 中使用动态组件,可以使用 <component> 元素,并通过 is 特性绑定一个组件的名称或组件对象。通过在父组件中改变 is 特性的值,可以动态切换渲染的组件。

第一种写法

  • A.vue
<template>
  <div>
    A component
  </div>
</template>

<script setup lang="ts">

</script>

<style scoped></style>

B.vue, C.vue 同理

  • APP.vue
<template>
  <div style="display: flex;">
    <!-- class可以写两个,一个静态,一个动态 -->
    <div @click="switchCom(item, index)" :class="[active == index ? 'active' : '']" class="tabs"
      v-for="(item, index) in data">
      <div>{{ item.name }}</div>
    </div>
  </div>
  <component :is="comId"></component>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue';
import AVue from './components/A.vue'
import BVue from './components/B.vue'
import CVue from './components/C.vue'
// 这里不需要将对象中所有数据变为响应式,可以使用ref
const comId = ref(AVue)
const active = ref(0)

const switchCom = (item, index) => {
  comId.value = item.com
  active.value = index
}

const data = reactive([
  {
    name: 'A',
    com: AVue
  },
  {
    name: 'B',
    com: BVue
  },
  {
    name: 'C',
    com: CVue
  }
])
</script>

<style lang="scss" scoped>
.active {
  background: blueviolet;
}

.tabs {
  border: 1px solid #ccc;
  padding: 5px 10px;
  margin: 5px;
  cursor: pointer;

}
</style>

第二种写法

  • APP.vue
<template>
  <div style="display: flex;">
    <!-- class可以写两个,一个静态,一个动态 -->
    <div @click="switchCom(item, index)" :class="[active == index ? 'active' : '']" class="tabs"
      v-for="(item, index) in data">
      <div>{{ item.name }}</div>
    </div>
  </div>
  <component :is="comId"></component>
</template>

<script setup lang="ts">
// markRaw:作用:标记一个对象,使其永远不会再成为响应式对象。
import { ref, reactive, markRaw, shallowRef } from 'vue';

// 这里不需要将对象中所有数据变为响应式,可以使用ref
const comId = shallowRef('AVue')
const active = ref(0)

const switchCom = (item, index) => {
  comId.value = item.com
  console.log(comId.value);
  
  active.value = index
}

const data = reactive([
  {
    name: 'A',
    com:'AVue'
  },
  {
    name: 'B',
    com:'BVue'
  },
  {
    name: 'C',
    com:'CVue'
  }
])
</script>

<script lang="ts">
import AVue from './components/A.vue'
import BVue from './components/B.vue'
import CVue from './components/C.vue'

export default {
  components: {
    AVue,
    BVue,
    CVue
  }
}
</script>

<style lang="scss" scoped>
.active {
  background: blueviolet;
}

.tabs {
  border: 1px solid #ccc;
  padding: 5px 10px;
  margin: 5px;
  cursor: pointer;

}
</style>

性能优化

上述第一种写法代码会出现警告

输出 comId 的值,出现 comId 的属性被劫持,出现性能浪费

解决方法

使用markRawshallowRef这两个API

  • App.vue
<template>
  <div style="display: flex;">
    <!-- class可以写两个,一个静态,一个动态 -->
    <div @click="switchCom(item, index)" :class="[active == index ? 'active' : '']" class="tabs"
      v-for="(item, index) in data">
      <div>{{ item.name }}</div>
    </div>
  </div>
  <component :is="comId"></component>
</template>

<script setup lang="ts">
// markRaw:作用:标记一个对象,使其永远不会再成为响应式对象。
import { ref, reactive, markRaw, shallowRef } from 'vue';
import AVue from './components/A.vue'
import BVue from './components/B.vue'
import CVue from './components/C.vue'
// 这里不需要将对象中所有数据变为响应式,可以使用ref
const comId = shallowRef(AVue)
const active = ref(0)

const switchCom = (item, index) => {
  comId.value = item.com
  console.log(comId.value);
  
  active.value = index
}

const data = reactive([
  {
    name: 'A',
    com: markRaw(AVue)
  },
  {
    name: 'B',
    com: markRaw(BVue)
  },
  {
    name: 'C',
    com: markRaw(CVue)
  }
])
</script>

<style lang="scss" scoped>
.active {
  background: blueviolet;
}

.tabs {
  border: 1px solid #ccc;
  padding: 5px 10px;
  margin: 5px;
  cursor: pointer;

}
</style>

再次输出 comId 的值,解决性能浪费的问题

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 第一次使用webstrom简单创建vue项目的一些报错实战记录

    第一次使用webstrom简单创建vue项目的一些报错实战记录

    在使用webstorm新建vue项目时常会遇到一些报错,特别是新手第一次运行项目,这篇文章主要给大家介绍了关于第一次使用webstrom简单创建vue项目的一些报错实战记录,需要的朋友可以参考下
    2023-02-02
  • 详解vue-cli项目中怎么使用mock数据

    详解vue-cli项目中怎么使用mock数据

    这篇文章主要介绍了vue-cli项目中怎么使用mock数据,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • vue项目中如何将当前页面生成图片

    vue项目中如何将当前页面生成图片

    这篇文章主要介绍了vue项目中如何将当前页面生成图片问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • 关于VUE点击父组件按钮跳转到子组件的问题及解决方案

    关于VUE点击父组件按钮跳转到子组件的问题及解决方案

    本文主要介绍了在Vue框架中,如何通过父组件的点击事件打开子组件中的弹窗并展示表格内容,主要步骤包括在父组件中定义数据属性,创建并定义子组件的弹窗和表格内容,通过props属性和自定义事件实现父子组件间的数据传递和方法调用
    2024-10-10
  • Vue实现tab切换的两种方法示例详解

    Vue实现tab切换的两种方法示例详解

    这篇文章主要介绍了Vue实现tab切换的两种方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-11-11
  • Vue 2源码解读$mount函数原理

    Vue 2源码解读$mount函数原理

    这篇文章主要为大家介绍了Vue 2源码解读$mount原理示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • VUE 单页面使用 echart 窗口变化时的用法

    VUE 单页面使用 echart 窗口变化时的用法

    这篇文章主要介绍了VUE 单页面使用 echart 窗口变化时的用法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • 详解vue-cli 3.0 build包太大导致首屏过长的解决方案

    详解vue-cli 3.0 build包太大导致首屏过长的解决方案

    这篇文章主要介绍了详解vue-cli 3.0 build包太大导致首屏过长的解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Vuex新手的理解与使用详解

    Vuex新手的理解与使用详解

    这篇文章主要介绍了Vuex新手的理解与使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • 基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

    基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

    这篇文章主要介绍了基于Vue3实现一个前端埋点上报插件并打包发布到npm,本项目采用pnpm进行Monorepo环境搭建,因为未来这个项目可能会加入更多的工具包,需要的朋友可以参考下
    2022-10-10

最新评论