随笔 - 12  文章 - 0  评论 - 0  阅读 - 6091

Vue3系列8--全局组件,局部组件,递归组件

1 配置全局组件

当一个组件使用频率非常高的时候,可以考虑设置其为全局组件,方便其他地方调用。

 案例------我这儿封装一个Card组件想在任何地方去使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<template>
    <div class="card">
        <div class="card-header">
            <div>主标题</div>
            <div>副标题</div>
        </div>
        <div v-if="content" class="card-content">
            {{ content }}
        </div>
    </div>
</template>
<script setup lang="ts">
type Props = {
    content?: string
}
 
defineProps<Props>()
</script>
 
<style scoped lang="less">
@border: #ccc;
.card {
    border: 1px solid;
    &:hover {
        box-shadow: 0 0 20px @border; //放在上面的效果
    }
    &-header {
        display: flex;
        justify-content: space-between;
        padding: 10px;
        border-bottom: 1px solid @border;
    }
    &-content {
        padding: 10px;
    }
}
</style>

使用方法:在main.ts 引入我们的组件跟随在createApp(App) 后面 切记不能放到mount 后面这是一个链式调用用,其次调用 component 第一个参数组件名称 第二个参数组件实例。

1
2
3
4
5
import { createApp } from 'vue'
import App from './App.vue'
import './assets/css/reset/index.less'
import Card from './components/Card/index.vue'
createApp(App).component('Card',Card).mount('#app')

使用方法:直接在其他vue页面 立即使用即可 无需引入

1
2
3
<template>
 <Card></Card>
</template>

2 配置局部组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
  <div class="wraps">
    <layout-menu :flag="flag" @on-click="getMenu" @on-toogle="getMenuItem" :data="menuList" class="wraps-left"></layout-menu>
    <div class="wraps-right">
      <layout-header> </layout-header>
      <layout-main class="wraps-right-main"></layout-main>
    </div>
  </div>
</template>
  
<script setup lang="ts">
import { reactive,ref } from "vue";
import layoutHeader from "./Header.vue";
import layoutMenu from "./Menu.vue";
import layoutMain from "./Content.vue";

就是在一个组件内(A) 通过import 去引入别的组件(B) 称之为局部组件,应为B组件只能在A组件内使用 所以是局部组件,如果C组件想用B组件 就需要C组件也手动import 引入 B 组件。

3 配置递归组件

原理跟我们写js递归是一样的 自己调用自己 通过一个条件来结束递归 否则导致内存泄漏

案例递归树:在父组件配置数据结构 数组对象格式 传给子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template><br>  <div><br>    <Tree :data="data"></Tree><br>  </div><br></template><br><br><script>import Tree from '../../components/Tree/index.vue'type TreeList = {
  name: string;
  icon?: string;
  children?: TreeList[] | [];
};
const data = reactive<TreeList[]>([
  {
    name: "no.1",
    children: [
      {
        name: "no.1-1",
        children: [
          {
            name: "no.1-1-1",
          },
        ],
      },
    ],
  },
  {
    name: "no.2",
    children: [
      {
        name: "no.2-1",
      },
    ],
  },
  {
    name: "no.3",
  },
]);</script>

子组件接收值 第一个script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type TreeList = {
  name: string;
  icon?: string;
  children?: TreeList[] | [];
};
  
type Props<T> = {
  data?: T[] | [];
};
  
defineProps<Props<TreeList>>();
  
const clickItem = (item: TreeList) => {
  console.log(item)
}

子组件增加一个script 定义组件名称为了 递归用 :

1
2
3
4
5
<script lang="ts">
export default {
  name:"TreeItem"
}
</script>

TreeItem 其实就是当前组件 通过import 把自身又引入了一遍 如果他没有children 了就结束:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
    <div style="margin-left: 10px;">
        <!-- {{data}} -->
        <div :key="index" v-for="(item, index) in data">{{ item.name }}
            <TreeItem v-if="item?.children?.length" :data="item.children"></TreeItem>
        </div>
    </div>
</template>
 
<script setup lang="ts">
import TreeItem from './index.vue'
type TreeList = {
    name: string,
    icon?: string,
    children?: TreeList[] | []
}
 
type Props = {
    data?: TreeList[]
}
 
defineProps<Props>()
 
</script>

4 动态组件

什么是动态组件 就是:让多个组件使用同一个挂载点,并动态切换,这就是动态组件。在挂载点使用component标签,然后使用v-bind:is=”组件”

用法如下:引入组件

1
2
3
import A from './A.vue'
import B from './B.vue'
import C from './C.vue'

 

1
<component :is="current.comName"></component>

通过is 切换 A B 组件,使用场景,tab切换 居多

注意事项

1.在Vue2 的时候is 是通过组件名称切换的 在Vue3 setup 是通过组件实例切换的

2.如果你把组件实例放到Reactive Vue会给你一个警告runtime-core.esm-bundler.js:38 [Vue warn]: Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with `markRaw` or using `shallowRef` instead of `ref`.Component that was made reactive:这是因为reactive 会进行proxy 代理 而我们组件代理之后毫无用处 节省性能开销 推荐我们使用shallowRef 或者 markRaw 跳过proxy 代理.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type Tabs = {
    name: string,
    comName: any
}
 
const data = reactive<Tabs[]>([
    {
        name: "我是组件A",
        comName: markRaw(A)
    },
    {
        name: "我是组件B",
        comName: markRaw(B)
    },
    {
        name: "我是组件C",
        comName: markRaw(C)
    },
])
 
type Com = Pick<Tabs, "comName">
 
let current = reactive<Com>({
    comName: data[0].comName
})
 
 
const switchTabs = (item: Tabs) => {
    current.comName = item.comName
}
posted on   LotusFlower  阅读(732)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示