10 vue3之全局组件,局部组件,递归组件,动态组件

发布于:2024-09-19 ⋅ 阅读:(14) ⋅ 点赞:(0)

全局组件

使用频率非常高的组件可以搞成全局组件,无需再组件中再次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


网站公告

今日签到

点亮在社区的每一天
去签到