mcpField
D
dynamic-components

dynamic-components

github.com/patternsdev开发257189 次安装28 周前更新
代码仓库

关于 dynamic-components

这是一项面向 Vue 开发者的技能,介绍如何在运行时切换组件,适用于构建标签页或视图界面。内容涵盖组件选择,以及切换时保留组件状态。

主要功能

  1. 01根据响应式选择切换组件
  2. 02用组件映射构建标签视图
  3. 03使用 KeepAlive 保留状态

适用场景

  1. 01无需路由构建标签页界面
  2. 02替代嵌套的 v-if/v-else 渲染
  3. 03切换标签时保留计数器状态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/patternsdev/skills --skill dynamic-components

安装后在 Claude Code 中输入/dynamic-components确认已加载。

详细介绍

动态组件

目录

动态组件可以通过将 is 属性绑定到保留的 <component> 元素,实现组件间的动态切换。

我们通过一个示例来更好地理解动态组件的工作方式。假设我们有三个独立的组件,分别名为 Home、Feed 和 History,它们只会显示说明当前组件名称的文本。

适用场景

  • 需要根据用户交互(例如标签页、视图)渲染不同组件时使用
  • 这可以作为多个 v-if/v-else 代码块的替代方案,用于有条件地渲染组件

使用说明

  • 将 <component> 上的 is 属性绑定到一个引用组件定义的响应式值
  • 使用 tabs 对象将名称映射到导入的组件定义
  • 使用 <KeepAlive> 包裹 <component>,以便在切换动态组件时保留状态

详情


<template><div class="tab">Home component</div></template>


<template><div class="tab">Feed component</div></template>


<template><div class="tab">History component</div></template>

我们的目标是构建一个显示标签页列表的界面,用户可以点击这些标签页。根据点击的标签页,我们希望动态渲染相应的组件。

在标签页之间切换时,我们希望无需使用路由,即可动态卸载和挂载组件。虽然使用 v-if 和 v-else 等指令有条件地渲染子模板也能实现类似效果,但 Vue 动态组件正适用于这种场景。

在应用的父级 App 组件中,我们可以先导入三个独立组件,以便在模板中使用它们。我们还会创建一个 currentTab 响应式属性,并将其初始值设为 "Home"。

<script setup>
  import { ref } from "vue";
  import Home from "./components/Home.vue";
  import Feed from "./components/Feed.vue";
  import History from "./components/History.vue";

  const currentTab = ref("Home");
  const tabs = {
    Home,
    Feed,
    History,
  };
</script>

请注意,我们的 tabs 对象引用的是实际的组件定义,而不只是组件名称。

在 App 组件模板中,我们要为计划显示的每个组件分别渲染一个标签页按钮,共三个。我们会使用 v-for 指令来实现这一点。

<template>
  <div class="demo">
    <button
      v-for="(_, tab) in tabs"
      :key="tab"
      :class="['tab-button', { active: currentTab === tab }]"
      @click="currentTab = tab"
    >
      {{ tab }}
    </button>
  </div>
</template>

要动态渲染特定的子组件,我们会将 is 属性绑定到保留的 <component> 元素。is 属性的值应与我们要动态渲染的子组件相对应。

<template>
  <div class="demo">
    <button
      v-for="(_, tab) in tabs"
      :key="tab"
      :class="['tab-button', { active: currentTab === tab }]"
      @click="currentTab = tab"
    >
      {{ tab }}
    </button>
    <component :is="tabs[currentTab]" class="tab"></component>
  </div>
</template>

<script setup>
  import { ref } from "vue";
  import Home from "./components/Home.vue";
  import Feed from "./components/Feed.vue";
  import History from "./components/History.vue";

  const currentTab = ref("Home");

  const tabs = {
    Home,
    Feed,
    History,
  };
</script>

将动态 <component /> 元素放入模板后,子组件便会根据所选标签页动态卸载和挂载。

保留状态

使用动态组件时,保留状态是一个重要的考量因素。默认情况下,组件卸载时,其状态会丢失。不过,Vue 提供了 <KeepAlive> 组件,可以保留动态组件的状态。

要保留动态组件的状态,我们可以使用 <KeepAlive> 组件包裹 <component> 元素。

<template>
  <div class="demo">
    
    <KeepAlive>
      <component :is="tabs[currentTab]" class="tab"></component>
    </KeepAlive>
  </div>
</template>

<script setup>
  // ...
</script>

使用 <KeepAlive> 组件包裹 <component> 元素后,动态组件卸载时其状态将得到保留。这意味着所有数据或组件状态都会维持不变,组件再次挂载时也会恢复先前的状态。

我们可以更新每个子组件,添加一个简单的递增计数器,来查看这一效果。


<template>
  <div class="tab">
    Home component
    <p>Counter: {{ counter }}</p>
    <button @click="incrementCounter">Increment</button>
  </div>
</template>

<script setup>
  import { ref } from "vue";

  const counter = ref(0);

  const incrementCounter = () => {
    counter.value++;
  };
</script>

经过这些更改,即使动态切换组件,每个子组件各自的计数器状态也会得到保留。

使用 <KeepAlive> 组件,我们可以通过保留动态组件的状态,改善其行为,并在标签页切换时提供更流畅的用户体验。

来源

References

评论

支持 Markdown