Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 动态组件与异步组件

动态组件与异步组件

Vue 3 提供了动态组件和异步组件两种机制,用于在运行时灵活加载和切换组件。动态组件通过 <component> 标签实现组件的动态渲染,而异步组件则通过懒加载优化性能,特别适合大型应用。本节将详细讲解这两者的用法、实现方式和应用场景,帮助你掌握这些高级组件化技术。

动态组件

动态组件允许在运行时根据条件切换渲染的组件,使用 <component> 标签和 :is 属性实现。

基本用法

示例:切换组件

<template>
  <div>
    <button @click="currentComponent = 'CompA'">显示 A</button>
    <button @click="currentComponent = 'CompB'">显示 B</button>
    <component :is="currentComponent" />
  </div>
</template>

<script>
import { ref } from 'vue';
import CompA from './CompA.vue';
import CompB from './CompB.vue';

export default {
  components: { CompA, CompB },
  setup() {
    const currentComponent = ref('CompA');
    return { currentComponent };
  }
};
</script>

子组件

<!-- CompA.vue -->
<template>
  <p>组件 A</p>
</template>
<!-- CompB.vue -->
<template>
  <p>组件 B</p>
</template>
  • 效果:点击按钮切换显示“组件 A”或“组件 B”。
  • 解析:
    • :is 绑定组件名称或组件对象。
    • 支持局部注册的组件或动态导入。

传递 Props 和事件

动态组件可以接收 Props 和监听事件:

<template>
  <div>
    <button @click="currentComponent = 'CompA'">显示 A</button>
    <button @click="currentComponent = 'CompB'">显示 B</button>
    <component :is="currentComponent" :message="message" @custom-event="handleEvent" />
  </div>
</template>

<script>
import { ref } from 'vue';
import CompA from './CompA.vue';
import CompB from './CompB.vue';

export default {
  components: { CompA, CompB },
  setup() {
    const currentComponent = ref('CompA');
    const message = ref('Hello from parent');
    const handleEvent = (value) => console.log('事件:', value);
    return { currentComponent, message, handleEvent };
  }
};
</script>

子组件(CompA.vue)

<template>
  <p>{{ message }}</p>
  <button @click="$emit('custom-event', 'From A')">触发事件</button>
</template>

<script>
export default {
  props: ['message'],
  emits: ['custom-event']
};
</script>
  • 效果:切换组件时传递消息,点击按钮触发事件。

keep-alive 缓存

使用 <keep-alive> 包裹动态组件,缓存实例状态:

<template>
  <div>
    <button @click="currentComponent = 'CompA'">显示 A</button>
    <button @click="currentComponent = 'CompB'">显示 B</button>
    <keep-alive>
      <component :is="currentComponent" />
    </keep-alive>
  </div>
</template>

<script>
import { ref } from 'vue';
import CompA from './CompA.vue';
import CompB from './CompB.vue';

export default {
  components: { CompA, CompB },
  setup() {
    const currentComponent = ref('CompA');
    return { currentComponent };
  }
};
</script>

子组件(CompA.vue)

<template>
  <div>
    <p>组件 A</p>
    <input v-model="input" />
  </div>
</template>

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

export default {
  setup() {
    const input = ref('');
    return { input };
  }
};
</script>
  • 效果:切换组件后,输入框内容保留。
  • 解析:<keep-alive> 缓存组件实例,避免销毁和重建。

异步组件

异步组件通过懒加载减少初始加载时间,适合按需加载大型或不常用的组件。

基本用法

使用 defineAsyncComponent 定义异步组件:

<template>
  <div>
    <button @click="showComponent = !showComponent">切换显示</button>
    <AsyncComp v-if="showComponent" />
  </div>
</template>

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

export default {
  components: {
    AsyncComp: defineAsyncComponent(() => import('./AsyncComp.vue'))
  },
  setup() {
    const showComponent = ref(false);
    return { showComponent };
  }
};
</script>

子组件(AsyncComp.vue)

<template>
  <p>异步加载的组件</p>
</template>
  • 效果:点击按钮时才加载 AsyncComp.vue。
  • 解析:import() 返回 Promise,组件按需加载。

加载状态与错误处理

支持加载中和错误时的自定义显示:

<template>
  <div>
    <button @click="showComponent = !showComponent">切换</button>
    <AsyncComp v-if="showComponent" />
  </div>
</template>

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

export default {
  components: {
    AsyncComp: defineAsyncComponent({
      loader: () => import('./AsyncComp.vue'),
      loadingComponent: { template: '<p>加载中...</p>' },
      errorComponent: { template: '<p>加载失败</p>' },
      delay: 200, // 加载前延迟(ms)
      timeout: 3000 // 超时时间(ms)
    })
  },
  setup() {
    const showComponent = ref(false);
    return { showComponent };
  }
};
</script>
  • 效果:
    • 加载前显示“加载中...”,延迟 200ms。
    • 超时 3s 显示“加载失败”。

与 Suspense 结合

Vue 3 的 <Suspense> 组件可统一管理异步组件的加载状态:

<template>
  <div>
    <button @click="showComponent = !showComponent">切换</button>
    <Suspense v-if="showComponent">
      <template #default>
        <AsyncComp />
      </template>
      <template #fallback>
        <p>加载中...</p>
      </template>
    </Suspense>
  </div>
</template>

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

export default {
  components: {
    AsyncComp: defineAsyncComponent(() => import('./AsyncComp.vue'))
  },
  setup() {
    const showComponent = ref(false);
    return { showComponent };
  }
};
</script>
  • 效果:加载期间显示“加载中...”,完成后渲染组件。
  • 注意:<Suspense> 是实验性特性,需关注其稳定性。

应用场景

动态组件

  • 选项卡:根据用户选择切换内容。
  • 模态框:动态加载不同弹窗内容。
  • 权限控制:根据角色渲染不同组件。

示例:选项卡

<template>
  <div>
    <button v-for="tab in tabs" :key="tab" @click="currentTab = tab">
      {{ tab }}
    </button>
    <keep-alive>
      <component :is="currentTab" />
    </keep-alive>
  </div>
</template>

<script>
import { ref } from 'vue';
import TabA from './TabA.vue';
import TabB from './TabB.vue';

export default {
  components: { TabA, TabB },
  setup() {
    const tabs = ['TabA', 'TabB'];
    const currentTab = ref('TabA');
    return { tabs, currentTab };
  }
};
</script>

异步组件

  • 路由懒加载:按需加载页面组件。
  • 大型模块:如图表库、编辑器。
  • 条件加载:仅在特定条件下加载。

示例:懒加载图表

<template>
  <div>
    <button @click="showChart = true">显示图表</button>
    <ChartComp v-if="showChart" />
  </div>
</template>

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

export default {
  components: {
    ChartComp: defineAsyncComponent(() => import('./ChartComp.vue'))
  },
  setup() {
    const showChart = ref(false);
    return { showChart };
  }
};
</script>

注意事项

  1. 动态组件命名:
    • 使用注册的组件名或导入的对象,避免字符串拼写错误。
  2. 异步组件性能:
    • 避免过多懒加载影响用户体验。
  3. 错误处理:
    • 配置 errorComponent 和 timeout 提升健壮性。

总结

动态组件和异步组件是 Vue 3 组件化开发的利器。动态组件通过 <component> 实现运行时切换,搭配 <keep-alive> 优化体验;异步组件通过 defineAsyncComponent 和 <Suspense> 实现懒加载,减少初始加载负担。掌握这些技术后,你可以灵活应对复杂场景。下一节将探讨插槽的使用,进一步丰富组件功能!

Last Updated:: 2/24/25, 10:48 AM