Vue学习记录之八(局部组件,全局组件,递归组件,动态组件)

一、局部组件

在src\components\Card.vue 建立一个文件,代码如下:

<template><div class="card"><header><div>标题</div><div>副标题</div></header><section>内容</section></div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'</script>
<style scoped lang="scss">
$border: #ccc;
.card{border: 1px solid $border;width: 400px;header{display: flex;justify-content: space-between;padding: 5px;border-bottom: 1px solid $border;}section{padding: 5px;min-height: 300px;}}
</style>

然后在要使用的文件中引入并使用。

<template><div><!--2、使用--><Card></Card></div>
</template>
<script setup lang='ts'>
//1、引入
import Card from './components/Card.vue';
</script>

二、全局组件

上面局部变量是谁使用,谁应用。而全局变量在配置中一次引入,任何地方都可以随时使用。
在main.ts 文件引入

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
//1、引入组件
import Card from './components/Card.vue';const app = createApp(App)
//2,注册组件为全局变量
app.component('Card',Card)
app.use(createPinia())
app.use(router)app.mount('#app')

然后在任意需要的地方,使用 即可。如果有何多组件,可以使用批量注册组件的方法进行。例如我们在element UI 中导入Icons下:

import * as ElementPlusIconsVue from '@element-plus/icons-vue' 
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}

三、递归组件

1)、父传子数据

<template><div><!--给子组件传递一个名为datas的变量,该变量数据下面已定义--><Tree :datas="data"></Tree></div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
import Tree from './components/Tree.vue';
interface Tree{name:string,checked: boolean,children?: Tree[]
}
const data = reactive<Tree[]>([{name:"1",checked:false,children:[{name:"1-1",checked:false,}]},{name:"2",checked:true,children:[{name:"2-1",checked:false,}]},{name:"3",checked:false,children:[{name:"3-1",checked:false,children:[{name:"3-1-1",checked:false,},{name:"3-1-2",checked:false,},]}]},
])</script>

2)、开始递归

在子组件中(Tree.vue)开始编写递归代码

1、直接使用组件名称来当成循环体
<template><div v-for="item in data" class="tree"><input type="checkbox" v-model="item.checked"><span>{{ item.name }}</span><!--下面开始递归:可以直接使用文件名当组件名,也就是自己用自己的文件名称来递归。绑定的数据要和上面循环的数据名称一致,既用上面的 :data,而且使用v-if来判断数组的长度,为真时递归--><Tree v-if="item?.children?.length" :data="item.children"></Tree><!--可选链操作符的使用(?)的使用,如果后面的属性不到的话,就返回undefined,避免报错。undefined隐式转换以后就是false,停止了循环。一般配合双问(??)好表达式进行使用,如果左边返回一个undefined或者null值的时候(而且只有是undefined或者null才可以),则可以返回双问号后面(右边)的值,有点类似三目运算符。undefined??123  返回1230??123  返回0--></div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
interface Tree{name:string,checked: boolean,children?: Tree[]
}
defineProps<{data?:Tree[]
}>()
</script>
<style lang="scss" scoped>
.tree{margin-left: 10px;
}
</style>
2、自定义一个名称用来递归

上面我们直接使用了文件名,如果感觉突兀,也可以自定义,在子组件中,新建一组script代码。

<template><div v-for="item in datas" class="tree"><input type="checkbox" v-model="item.checked"><span>{{ item.name }}</span><!--递归体使用自定义的LvmanbaTree--><LvmanbaTree v-if="item.children?.length" :datas="item.children"></LvmanbaTree></div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
interface Tree{name:string,checked: boolean,children?: Tree[]
}
defineProps<{datas?:Tree[]
}>()
</script>
<script lang="ts">
export default{name="LvmanbaTree"
}
</script>
3、使用插件

第二种方法虽然可以自定了循环名称了,但是也要增加一组

第一步: 安装插件

pnpm add -D unplugin-vue-define-options @vue-macros/volar

第二步:在vite.config.ts中进行配置

//1、引入组件
import DefineOptions from 'unplugin-vue-define-options/vite'export default defineConfig({//2、在plugins中注册下,使用DefineOpetions()plugins: [DefineOptions()],
})

第三步:
在tsconfig.json 进行如下配置:就出现了代码提示了。

{"compilerOptions": {// ..."types": ["unplugin-vue-define-options/macros-global" /* ... */]}
}

第四步: 使用
它提供一个编译宏,必须使用这个插件,才能使用defineOptions. 这个是插件提供的,这样就不用再写一个

defineOptions({name:"LvmanbaTree"
})
4、接收tree的点击事件
<template><!--不加stop,出现冒泡事件--><div @click.stop="clickTap(item)" v-for="item in datas" class="tree"><input type="checkbox" v-model="item.checked"><span>{{ item.name }}</span><!--递归体使用自定义的LvmanbaTree--><LvmanbaTree v-if="item.children?.length" :datas="item.children"></LvmanbaTree></div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
interface Tree{name:string,checked: boolean,children?: Tree[]
}
defineProps<{datas?:Tree[]
}>()
const clickTap = (item: Tree) =>{console.log(item)
}
</script>
<script lang="ts">export default{name:"LvmanbaTree"}
</script>
<style lang="scss" scoped>
.tree{margin-left: 10px;
}
</style>

也可以传递事件

<template><div @click.stop="clickTap(item,$event)" v-for="item in datas" class="tree"><input type="checkbox" v-model="item.checked"><span>{{ item.name }}</span><Tree v-if="item.children?.length" :datas="item.children"></Tree></div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
interface Tree{name:string,checked: boolean,children?: Tree[]
}
defineProps<{datas?:Tree[]
}>()
const clickTap = (item: Tree,e) =>{//console.log(item)console.log(e.target)
}
</script><style lang="scss" scoped>
.tree{margin-left: 10px;
}
</style>

四、 动态组件

动态组件,就是多个组件使用同一个挂载点,也就是一个位置,可以动态切换的显示多个组件。 在挂载点使用 component标签,然后在使用v-bind:is = “组件”。 应用场景,典型的tab切换。当然也可以使用动态路由来实现。

实例: 效果如下。
在这里插入图片描述
第一步: 先创建三个组件
在这里插入图片描述
第二步:编写代码
一个标签内可以有两个想通的属性,但是必须一个静态,另外一个是动态。另外一个难理解的地方就是就把一个组件赋值给一个变量。

<template><div style="display: flex;"><div @click="switchCom(item,index)"v-for="(item,index) in data" class="tabs" :class="[active == index ? 'active':'']"><div>{{ item.name }}</div></div></div><component :is="comId"></component>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
import AVue from './components/A.vue';
import BVue from './components/B.vue';
import CVue from './components/C.vue';
const comId = ref(AVue)
const active = ref(0)
const switchCom =(item,index:number) =>{active.value = index,comId.value = item.com
}
const data = reactive([{name:"A组件",com: AVue  //此时的变量是一个组件},{name:"B组件",com: BVue},{name:"C组件",com: CVue}])
</script>
<style scoped>
.active{background: skyblue;
}
.tabs{border: solid 1px #ccc;padding: 5px 10px;margin: 5px;cursor: pointer; /* 鼠标放上去变成小手 */
}
</style>

上面代码可以正常使用,但是在控制台有错误报错,原因就是组件变量导致的。
在这里插入图片描述
错误的引发:他包括了一些组件的信息,这里的属性没有必要去劫持,因此我们需要跳过它,他提供了2个API,第一个是shallowRef(它是代理最外面的一层), 另外一个是markRaw(它是在对象里面,它有一个skip属性,reactive如果碰到这个属性,也会跳过proxy代理)
在这里插入图片描述

错误修复如下:

<script setup lang='ts'>
import { ref,reactive,markRaw,shallowRef } from 'vue'
import AVue from './components/A.vue';
import BVue from './components/B.vue';
import CVue from './components/C.vue';
// 修改错误第一处,使用shallowRef
const comId = shallowRef(AVue)
const active = ref(0)
const switchCom =(item,index:number) =>{active.value = index,comId.value = item.comconsole.log(comId.value)
}
// 修改错误第二处,使用markRaw
const data = reactive([{name:"A组件",com: markRaw(AVue)},{name:"B组件",com: markRaw(BVue)},{name:"C组件",com: markRaw(CVue)}])
</script>

第二种方法:

<template><div style="display: flex;"><div @click="switchCom(item,index)"v-for="(item,index) in data" class="tabs" :class="[active == index ? 'active':'']"><div>{{ item.name }}</div></div></div><component :is="comId"></component>
</template>
<script setup lang='ts'>
import { ref,reactive,shallowRef } from 'vue'// 修改错误第一处,使用shallowRef
const comId = shallowRef('AVue')
const active = ref(0)
const switchCom =(item,index:number) =>{active.value = index,comId.value = item.comconsole.log(comId.value)
}
const data = reactive([{name:"A组件",com: "AVue"},{name:"B组件",com: "BVue"},{name:"C组件",com: "CVue"}])
</script>
<script lang="ts">
import AVue from './components/A.vue';
import BVue from './components/B.vue';
import CVue from './components/C.vue';
export default{components:{AVue,BVue,CVue}
}
</script>
<style scoped>
.active{background: skyblue;
}
.tabs{border: solid 1px #ccc;padding: 5px 10px;margin: 5px;cursor: pointer; /* 鼠标放上去变成小手 */
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/430590.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HTML5】html5开篇基础(1)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

【标准库的典型内容】std::declval

一、 d e c l v a l declval declval的基本概念和常规范例 s t d : : d e c l v a l std::declval std::declval 是 C 11 C11 C11标准中出现的一个函数模板。这个函数模板设计的比较奇怪&#xff08;没有实现&#xff0c;只有声明&#xff09;&#xff0c;因此无法被调用&…

Android15之编译Cuttlefish模拟器(二百三十一)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

OpenCV特征检测(5)检测图像中的角点函数cornerMinEigenVal()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算用于角点检测的梯度矩阵的最小特征值。 该函数类似于 cornerEigenValsAndVecs&#xff0c;但它计算并存储协方差矩阵导数的最小特征值&…

MovieLife 电影生活

MovieLife 电影生活 今天看到一个很有意思的项目&#xff1a;https://www.lampysecurity.com/post/the-infinite-audio-book “我有一个看似愚蠢的想法。通常&#xff0c;这类想法只是一闪而过&#xff0c;很少会付诸实践。但这次有所不同。假如你的生活是一部电影&#xff0c…

vi | vim基本使用

vim三模式&#xff1a;① 输入模式 ②命令模式 ③末行模式&#xff08;编辑模式&#xff09; vim四模式&#xff1a;① 输入模式 ②命令模式 ③末行模式&#xff08;编辑模式&#xff09; ④V模式 一、命令模式进入输入模式方法&#xff1a; 二、命令模式基…

影刀RPA实战:java结合影刀同步采购订单数据

1.实战目标 本次实战我们用java语言结合影刀&#xff0c;实现从自用ERP系统同步订单到旺店通中&#xff0c;在工作中&#xff0c;有时候我们的运营数据不是直接在旺店通ERP中操作&#xff0c;比如我们有自己的ERP&#xff0c;完成一些特定的内部工作后&#xff0c;再把数据同步…

Rustrover2024.2 正式发布:个人非商用免费,泰裤辣

如果这个世界本身 已经足够荒唐 那究竟什么才能算是疯狂 爱情就是这样 一旦错过了 就会有另一个人代替 我们知道 jetbrains 在今年的早些时候正式为 rust 语言发布了专用的 IDE &#xff0c;也就是 rustrover。如今 rustrover 也正式跻身为 jetbrains IDE 系列的一员猛将。…

Python | Leetcode Python题解之第424题替换后的最长重复字符

题目&#xff1a; 题解&#xff1a; class Solution:def characterReplacement(self, s: str, k: int) -> int:num [0] * 26n len(s)maxn left right 0while right < n:num[ord(s[right]) - ord("A")] 1maxn max(maxn, num[ord(s[right]) - ord("…

Linux学习笔记13---GPIO 中断实验

中断系统是一个处理器重要的组成部分&#xff0c;中断系统极大的提高了 CPU 的执行效率&#xff0c;本章会将 I.MX6U 的一个 IO 作为输入中断&#xff0c;借此来讲解如何对 I.MX6U 的中断系统进行编程。 GIC 控制器简介 1、GIC 控制器总览 I.MX6U(Cortex-A)的中断控制器…

科研绘图系列:R语言堆积图(stacked barplot)

文章目录 介绍加载R包导入数据数据预处理画图导出数据系统信息介绍 微生物堆积图是一种数据可视化工具,通常用于展示微生物群落中不同物种的相对丰度。这种图表通过将每个样本中的微生物按照其分类学等级(如门、属等)进行分类,并以不同颜色的块状图表示,每个块的大小代表…

信息安全工程师(13)网络攻击一般过程

前言 网络攻击的一般过程是一个复杂且系统化的行为&#xff0c;其目标往往在于未经授权地访问、破坏或窃取目标系统的信息。 一、侦查与信息收集阶段 开放源情报收集&#xff1a;攻击者首先会通过搜索引擎、社交媒体、论坛等公开渠道获取目标的基本信息&#xff0c;如姓名、地址…

科研小白入门工具

三、科研绘图 1.流程图绘制工具&#xff1a;powerpoint、亿图图示、visio、draw.io 2.绘制标准&#xff1a;布局合理、色彩鲜明、字体大小、矢量输出 矢量图绘制推荐流程&#xff1a;亿图图示绘制--visio--word--pdf无损放大 3.文章插图&#xff1a;excel、origin、matlab、…

Linux——虚拟机网络配置

进行虚拟机网络配置是确保虚拟机能够正常访问网络、与宿主机及其他设备进行通信的关键步骤。虚拟机网络配置允许用户根据实际需求选择合适的网络模式&#xff0c;并调整网络参数以满足特定的网络环境要求。 虚拟机常见的三种网络模式包括桥接模式、NAT模式和主机模式&#xff…

甩锅笔记:好好的服务端应用突然起不来,经定位是无法访问外网了?测试又说没改网络配置,该如何定位?

在工作中、团队协作时&#xff0c;可能遇到的问题&#xff0c;如集成测试等场景。但是作为偏前端的全栈&#xff0c;锅从天上来&#xff0c;不是你想甩就能甩&#xff0c;尤其面对测试等比较强势的团体&#xff08;bug创造者&#xff09;&#xff0c;你必须有强大的心理承受能力…

热斑黄斑光伏发电板 红外黄斑检测图像数据集内含最高温度信息 1200张,jpg格式。

热斑黄斑光伏发电板 红外黄斑检测图像数据集 内含最高温度信息 1200张&#xff0c;jpg格式。 热斑黄斑光伏发电板红外黄斑检测图像数据集介绍 数据集名称 热斑黄斑光伏发电板红外黄斑检测图像数据集&#xff08;Hot Spot and Yellow Spot Detection in Photovoltaic Panels I…

C++之STL—vector容器进阶篇

vector容器的迭代器是支持随机访问的迭代器&#xff08;动态数组&#xff09; 构造函数 赋值操作 vector容量和大小 判断是否为空 --- empty 返回元素个数 --- size 返回容器容量 --- capacity 重新指定大小 --- resize vector插入和删除 * 尾插 --- push_back * …

手势手语识别数据集,YOLOv5目标检测两个数据集,图大量,模型精度高分别为近100类

手势手语识别数据集&#xff0c;YOLOv5目标检测 两个数据集&#xff0c;图大量&#xff0c;模型精度高分别为近100类 手势手语识别数据集&#xff08;Sign Language Gesture Recognition Dataset&#xff09; 数据集概述 该数据集专为手势手语识别设计&#xff0c;包含大量的…

AOT源码解析4.1-model主体解析

1 输入数据 VOS的数据集处理操作可见数据集操作&#xff0c;这里是进行数据集提取完毕后的操作。 图2&#xff1a;如图所示&#xff0c;使用datasets提取出数据之后&#xff0c;在模型训练阶段对数据做图中操作。即&#xff1a;将batch_size大小的ref_imgs、prev_imgs&#x…

【QT】QSS基础

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;基本语法&#x1f449;&#x1f3fb;从⽂件加载样式表&#x1f449;&#x1f3fb;选择器伪类选择器 &#x1f449;&…