Vue3-全局组件 && 递归组件

1.全局组件

全局组件是在 main.ts 中一次性注册,之后就可以在项目中的任何 组件模板内直接使用,无需 import

组件本身就是一个标准的 SFC (单文件组件),使用 <script setup lang="ts"> 编写。

举个栗子,button组件

ts 复制代码
<template>
  <button class="base-button">
    <slot></slot>
  </button>
</template>

<script setup lang="ts">
// 这里可以定义 props, emits 等
// 例如:
// defineProps<{ type: 'primary' | 'secondary' }>()
</script>

<style scoped>
.base-button {
  padding: 8px 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
  cursor: pointer;
}
.base-button:hover {
  background-color: #f0f0f0;
}
</style>

在创建 Vue 实例后、挂载 (.mount()) 之前来注册它。

app.component('组件名', 组件对象)

ts 复制代码
// main.ts
import { createApp } from 'vue'
import App from './App.vue'

// 1. 导入要全局注册的组件
import BaseCard from './components/BaseCard.vue'
import BaseButton from './components/BaseButton.vue'
import SvgIcon from './components/SvgIcon.vue'

const app = createApp(App)

// 2. 使用 app.component() 进行全局注册
// app.component('组件名', 组件对象)
app.component('BaseCard', BaseCard)
app.component('BaseButton', BaseButton)
app.component('SvgIcon', SvgIcon)

// 3. 挂载应用
app.mount('#app')

注册后,在任何 其他组件中都可以直接使用 <BaseButton>,无需导入。

ts 复制代码
<template>
  <div>
    <h1>欢迎!</h1>
    <BaseButton>点我</BaseButton>
    <BaseCard>
      <SvgIcon name="user" />
      <p>一些内容</p>
    </BaseCard>
  </div>
</template>

<script setup lang="ts">
// 无需 import BaseButton, BaseCard, SvgIcon
</script>
使用场景
  1. 基础 UI 组件: 这是最常见的场景。项目中使用频率极高的组件,例如 Button, Icon, Modal, Card, Input 等。通常会以 Base-App- 作为前缀,以示区分。
  2. UI 库集成: 当使用像 Element Plus, Naive UI 或 Vuetify 这样的库时,它们通常会提供一个 app.use(Library) 的方式,这背后其实就是全局注册了它们所有的组件。
  3. 布局组件: AppHeader, AppFooter, Sidebar 等几乎每个页面都会用到的布局框架。

⚠️ 注意: 全局注册会轻微增加应用的初始加载体积 ,因为所有全局组件都会被打包到主 chunk 中。因此,请对那些真正常用的组件使用全局注册,避免滥用。


2.递归组件

递归组件是指在其模板中调用自身的组件。

举个栗子:树形菜单

首先,定义数据结构 ( types.ts)

ts 复制代码
// types.ts
export interface TreeNodeData {
  id: string;
  label: string;
  children?: TreeNodeData[]; // 关键:children 数组的类型是它自身
}

然后,创建递归组件 (TreeNode.vue)

ts 复制代码
<template>
  <div class="tree-node">
    <div class="node-label">{{ node.label }}</div>
    <!-- 可选链操作符?.:如果 node.children 存在且有值,则渲染子节点列表,否则返回undefined,隐式转换为false -->
    <ul v-if="node.children && node.children.length > 0" class="children-list">
      <li v-for="child in node.children" :key="child.id">
        <!-- 递归 -->
        <TreeNode :node="child" />
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
// 导入我们定义的类型
import type { TreeNodeData } from './types'

// 1. 定义 Props,接收父组件传递的数据
interface Props {
  node: TreeNodeData;
}
defineProps<Props>()

</script>

<style scoped>
.tree-node {
  margin-left: 20px;
}
.node-label {
  font-weight: bold;
}
.children-list {
  list-style-type: none;
  padding-left: 15px;
  border-left: 1px dashed #ccc;
}
</style>

在父组件中导入并渲染"根节点"即可。

ts 复制代码
<template>
  <div>
    <h1>文件结构树</h1>
    <TreeNode :node="fileTree" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import TreeNode from './components/TreeNode.vue'
import type { TreeNodeData } from './components/types' // 确保路径正确

// 准备一个符合 TreeNodeData 结构的 TS 数据
const fileTree = ref<TreeNodeData>({
  id: 'root',
  label: '项目根目录 (src)',
  children: [
    {
      id: 'c1',
      label: 'components',
      children: [
        { id: 'c1-1', label: 'TreeNode.vue' },
        { id: 'c1-2', label: 'BaseButton.vue' },
      ],
    },
    {
      id: 'c2',
      label: 'views',
      children: [
        { id: 'c2-1', label: 'HomePage.vue' },
      ],
    },
    {
      id: 'c3',
      label: 'App.vue',
      // 这个节点没有 children,递归将在此处停止
    },
  ],
})
</script>
使用场景
  1. 树形结构: 任何需要展示层级关系的数据。例如:文件浏览器、组织架构图、导航菜单(尤其是多级下拉菜单)。
  2. 嵌套评论: 社交媒体或论坛中的评论区,一条评论可以有"回复"(子评论),子评论又可以有回复。
  3. JSON 格式化器: 展示一个 JSON 对象,如果某个值是对象或数组,就递归地调用组件来展示其内部。

参考文章

小满zs 学习Vue3 第十五章(全局组件,局部组件,递归组件)xiaoman.blog.csdn.net/article/det...

相关推荐
玖月晴空2 小时前
探索关于Spec 和Skills 的一些实战运用-Kiro篇
前端·aigc·代码规范
子兮曰2 小时前
深入理解滑块验证码:那些你不知道的防破解机制
前端·javascript·canvas
weixin79893765432...2 小时前
Vue 组件的更新过程(编译系统 + 响应式系统 + 虚拟 DOM & Diff)
vue.js
会一丢丢蝶泳的咻狗2 小时前
Sass实现,蛇形流动布局
前端·css
攀登的牵牛花2 小时前
前端向架构突围系列 - 状态数据设计 [8 - 4]:有限状态机 (FSM) 在复杂前端逻辑中的应用
前端
Lsx_2 小时前
前端视角下认识 AI Agent 和 LangChain
前端·人工智能·agent
我是伪码农3 小时前
Vue 智慧商城项目
前端·javascript·vue.js
不认输的西瓜3 小时前
fetch-event-source源码解读
前端·javascript
用户39051332192883 小时前
前端性能杀手竟然不是JS?图片优化才是绝大多数人忽略的"降本增效"方案
前端
朱昆鹏3 小时前
开源 Claude Code + Codex + 面板 的未来vibecoding平台
前端·后端·github