10 vue3之全局组件,局部组件,递归组件,动态组件
全局组件
使用频率非常高的组件可以搞成全局组件,无需再组件中再次import引入
在main.ts 注册
import Card from './components/Card/index.vue'
createApp(App).component('Card',Card).mount('#app')
使用方法
直接在其他vue页面 立即使用即可 无需引入
<template>
<card></card>
</template>
批量注册全局组件
可以参考element ui 其实就是遍历一下然后通过 app.component 注册
局部组件
在组件内部使用import引入的
<template>
<div class=""></div>
<son></son>
<son2 :title="'父组件传来的title'"></son2>
</template>
<script setup lang="ts">
import son from "./components/son_eight.vue";
import son2 from "./components/son_eight2.vue";
</script>
配置递归组件
原理跟我们写js递归是一样的 自己调用自己 通过一个条件来结束递归 否则导致内存泄漏
案例递归树
在父组件配置数据结构 数组对象格式 传给子组件
<script setup lang="ts">
<template>
<h2>递归组件案例--</h2>
<Tree @emit="get" :data="data"></Tree>
</template>
<script setup lang="ts">
import {
ref,
reactive,
markRaw,
shallowRef,
shallowReactive,
} from "vue";
import Tree from "./components/nine_tree.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",
},
]);
let get = (name) => {
console.log("父组件接收的值", name);
};
</script>
TreeItem.vue子组件 直接使用组件名字
<template>
<div
style="margin-left: 40px"
:key="index"
@click.stop="send(item)"
v-for="(item, index) in data"
>
<div>{{ item.name }}</div>
<!--
@emit="send" 组件需要再次派发 这里是细节的地方
控制台输出以下内容
let obj = {
name: ''
}
obj.children // undefined
obj.children.length // 直接报错
obj.children?.length // undefined
obj.children?.length ?? 1 // 1
null ?? 1 // 1
false ?? 1 // false ,?? 只处理左边undefined 和null 的情况
-->
<TreeItem
@emit="send"
v-if="item?.children?.length"
:data="item.children"
></TreeItem>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
type TreeList = {
name: string;
icon?: string;
children?: TreeList[] | []; // 代表children可以不传 也可以传但是接收的同样是TreeList类型 也可以传空数组
};
type Props = {
data?: TreeList | []; // 这里处理很细节
};
defineProps<Props>();
let emit = defineEmits(["emit"]);
let send = (item) => {
emit("emit", item);
};
</script>
或者再次添加个script
<script lang="ts">
export default {
name:"TreeItem"
}
</script>
效果图:
动态组件
父组件
<template>
<h3>动态组件案例--</h3>
<!-- 不能是两个动态的 最多只支持一个动态和一个静态 -->
<div
:class="[active == index ? 'active' : '']"
v-for="(item, index) in comList"
:key="index"
>
<button @click="switchTab(item)">{{ item.tab }}</button>
</div>
<component :is="current.name"></component>
<h3>字符串的方式</h3>
<component is="C"></component>
</template>
<script setup lang="ts">
import {
ref,
reactive,
markRaw,
shallowRef,
shallowReactive,
} from "vue";
import A from "./components/nine_A.vue";
import B from "./components/nine_B.vue";
import C from "./components/nine_C.vue";
// 动态组件
// vue2中是通过组件的name做渲染,vue3中setup是通过组件的实例来做渲染
type Com = {
tab: string;
name: string;
};
type Cur = Pick<Com, "name">; // Pick 从Com中提取出name 作为字面量泛型
let comList = reactive<Com[]>([
{
tab: "我是A组件",
name: shallowReactive(A),
// name: "A", // 警告是由于reactive做了代理proxy 导致组件也做了代理,组件代理是没必要的所以节省开销我们使用 ShallowReactive, ShallowReactive,show
},
{
tab: "我是B组件",
name: shallowReactive(B),
},
]);
let active = ref<number>(0);
let current = reactive<Cur>({
name: comList[0].name, // 默认展示第一个组件
});
let switchTab = (item, index) => {
current.name = item.name;
active.value = index;
console.log(current.name.value);
};
</script>
<script lang="ts">
export default {
components: {
C,
},
};
</script>
<style lang="scss" scoped>
.active {
background: pink;
}
</style>
A.vue
<template>
<div class="">aaaaaaaaaaaaaa</div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
</script>
<style lang="sass" scoped></style>
B.vue
<template>
<div class="">bbbbbbbb</div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
</script>
<style lang="sass" scoped></style>
C.vue
<template>
<div class="">
<h3>vue3 第二种动态组件的方式使用</h3>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
</script>
<style lang="sass" scoped></style>
效果图:
11 vue3之插槽全家桶-CSDN博客11 vue3之插槽全家桶。https://blog.csdn.net/qq_37550440/article/details/142326456?sharetype=blogdetail&sharerId=142326456&sharerefer=PC&sharesource=qq_37550440&spm=1011.2480.3001.8118