当前位置: 首页 > article >正文

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


http://www.kler.cn/a/316102.html

相关文章:

  • 研究生如何远控实验室电脑?远程办公功能使用教程
  • 【Visual Studio】使用VS调试(Debug)
  • 蓝队知识浅谈(上)
  • Llama架构及代码详解
  • Could not initialize class sun.awt.X11FontManager
  • Python →爬虫实践
  • 博睿谷IT认证-订阅试学习
  • 利用H5无插件播放RTSP流的实现方案
  • Vue3 路由传参:玩转 params,让页面交互更流畅!
  • 什么是堡垒机?运维为什么需要堡垒机?
  • ES 索引或索引模板
  • 【图像匹配】基于SIFT算法的图像匹配,matlab实现
  • ECMAScript与JavaScript的区别:深入解析与代码实践
  • 出厂非澎湃OS手机解BL锁
  • STM32篇:通用输入输出端口GPIO
  • 智谱清影的魅力:使用CogVideoX-2b生成6秒视频的真实体验!
  • 信息安全工程师(10)网络信息安全法律与政策文件
  • jvm中的程序计数器、虚拟机栈和本地方法栈
  • Spring8-事务
  • git安装geographiclib失败解决办法
  • GPT对话知识库——编写IIC驱动的过程
  • 位图与布隆过滤器
  • docker minio启动命令
  • ARM/Linux嵌入式面经(三六):中科曙光
  • Docker:安装Apache Pulsar 消息队列的详细指南
  • Python 课程16-Pygame