vue-插槽作用域实用场景
vue-插槽作用域实用场景
- 1.插槽
- 1.1 自定义列表渲染
- 1.2 数据表格组件
- 1.3 树形组件
- 1.4 表单验证组件
- 1.5 无限滚动组件
1.插槽
插槽感觉知道有这个东西,但是挺少用过的,每次看到基本都会再去看一遍用法和概念。但是在项目里,自己还是没有用到过。总结下一些可能用到的场景,下次直接这样写了。
1.1 自定义列表渲染
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import { reactive } from 'vue';
const myItems = reactive([{name: 'A',age: 18},{name: 'B',age: 19},{name: 'C',age: 20}
]
)
</script>
<template><HelloWorld :items="myItems"><template v-slot:default="slotProps"><span>{{ slotProps.item.name }}</span><button @click="doSomething(slotProps.item)">操作</button></template></HelloWorld>
</template><script setup>
import { defineProps } from 'vue';defineProps({items: {type: Array,default: () => []}
})
</script>
<template><ul><li v-for="item in items" :key="item.id"><slot :item="item"></slot></li></ul>
</template>
效果:

拓展性很强。
1.2 数据表格组件
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import { reactive } from 'vue';
const tableData = reactive([{name: 'A',age: 18},{name: 'B',age: 19},{name: 'C',age: 20}]
)const columns = reactive([{label: '姓名',key: 'name'},{label: '年龄',key: 'age'},{label: '性别',key: 'sex'},{ key: 'actions', label: '操作' }]
)
</script>
<template><HelloWorld :columns="columns" :data="tableData"><template v-slot:actions="{ row }"><button @click="edit(row)">编辑</button><button @click="del(row)">删除</button></template></HelloWorld>
</template><template><table><thead><tr><th v-for="column in columns" :key="column.key">{{ column.label }}</th></tr></thead><tbody><tr v-for="row in data" :key="row.id"><td v-for="column in columns" :key="column.key"><slot :name="column.key" :row="row">{{ row[column.key] }}</slot></td></tr></tbody></table>
</template><script setup>
import { defineProps } from 'vue';
defineProps({columns: Array,data: Array,
});
</script>
效果:

1.3 树形组件
<template><div class="tree-node"><slot :node="node" :toggle="toggle" :expandTree="expandTree" name="trangle"><span v-if="node.children.length > 0" @click="toggle">{{ expanded ? '▼' : '▶' }}</span></slot><slot :node="node" :toggle="toggle" :expandTree="expandTree"><div>{{ node.label }}</div></slot><div v-if="expanded" class="tree-node-children"><HelloWorld v-for="child in node.children" :key="child.id" :node="child"><template v-slot="childSlotProps"><slot v-bind="childSlotProps"></slot></template></HelloWorld></div></div>
</template>
<script setup>
import HelloWorld from './HelloWorld.vue'
import { defineProps, ref } from 'vue';
const props = defineProps({node: {type: Object,required: true}
})
const expanded = ref(false)
const toggle = () => {console.log(999)expanded.value = !expanded.value
}
const expandTree = () => {expanded.value = true
}
</script>
<style>
.tree-node {position: relative;cursor: pointer;
}.tree-node-children {position: relative;padding-left: 20px;/* 这个值决定了每一层的缩进量 */
}.tree-node>span {margin-left: 0;
}
</style><script setup>
import HelloWorld from './components/HelloWorld.vue'
import { reactive } from 'vue';const rootNode = reactive({id: 1,label: '根节点',children: [{id: 2, label: '子节点1', children: [{ id: 3, label: '子节点1-1', children: [] }]},{ id: 4, label: '子节点2', children: [] }]
})const addChild = (node, expandTree) => {const newId = Date.now()expandTree()node.children.push({id: newId,label: `新子节点${newId}`,children: []})
}
</script>
<template><HelloWorld :node="rootNode"><template v-slot="{ node, toggle, expandTree }"><span @click="toggle">{{ node.label }}</span><button @click="addChild(node, expandTree)">添加子节点</button></template></HelloWorld>
</template>
效果:

1.4 表单验证组件
<script setup>
import { ref, watch, defineProps, defineEmits } from 'vue'const props = defineProps({rules: {type: Array,default: () => []},modelValue: {type: String,default: ''}
})const emit = defineEmits(['update:modelValue'])const value = ref(props.modelValue)
const error = ref('')const validate = () => {for (const rule of props.rules) {if (!rule.validate(value.value)) {error.value = rule.messagereturn false}}error.value = ''return true
}watch(() => props.modelValue, (newValue) => {value.value = newValue
})watch(value, (newValue) => {emit('update:modelValue', newValue)
})
</script><template><div class="a"><slot :value="value" :error="error" :validate="validate"></slot><span v-if="error">{{ error }}</span></div>
</template>
<style lang="scss" scoped>
.a{position: relative;span{color: red;position: absolute;left: 0;bottom: -24px;font-size: 14px;}
}</style>//使用
<script setup>
import FormField from './components/HelloWorld.vue'
import { ref } from 'vue';const email = ref('')const emailRules = [{validate: (value) => /.+@.+\..+/.test(value),message: '请输入有效的电子邮件地址'}
]
</script>
<template><FormField :rules="emailRules" v-model="email"><template v-slot="{ value, error, validate }">邮箱<input :value="value" @input="$event => { email = $event.target.value; validate(); }":class="{ 'is-invalid': error }" /></template></FormField>
</template><style >
input{outline: none;
}
.is-invalid:focus {border-color: red;
}
</style>
效果:

1.5 无限滚动组件
<script setup>
import { ref, onMounted, defineProps } from 'vue'const props = defineProps({fetchItems: {type: Function,required: true}
})const visibleItems = ref([])
const loading = ref(false)const handleScroll = async (event) => {const { scrollTop, scrollHeight, clientHeight } = event.targetif (scrollTop + clientHeight >= scrollHeight - 20 && !loading.value) {loading.value = trueconst newItems = await props.fetchItems()visibleItems.value = [...visibleItems.value, ...newItems]loading.value = false}
}onMounted(async () => {visibleItems.value = await props.fetchItems()
})
</script><template><div @scroll="handleScroll" style="height: 200px; overflow-y: auto;"><slot :items="visibleItems"></slot><div v-if="loading">加载中...</div></div>
</template>//使用
<script setup>
import InfiniteScroll from './components/HelloWorld.vue'
import { ref } from 'vue';let page = 0
const fetchMoreItems = async () => {// 模拟API调用await new Promise(resolve => setTimeout(resolve, 1000))page++return Array.from({ length: 10 }, (_, i) => ({id: page * 10 + i,content: `Item ${page * 10 + i}`}))
}
</script>
<template><InfiniteScroll :fetch-items="fetchMoreItems"><template #default="{ items }"><div v-for="item in items" :key="item.id">{{ item.content }}</div></template></InfiniteScroll>
</template>相关文章:
vue-插槽作用域实用场景
vue-插槽作用域实用场景 1.插槽1.1 自定义列表渲染1.2 数据表格组件1.3 树形组件1.4 表单验证组件1.5 无限滚动组件 1.插槽 插槽感觉知道有这个东西,但是挺少用过的,每次看到基本都会再去看一遍用法和概念。但是在项目里,自己还是没有用到过…...
Prometheus+Grafana 监控 K8S Ingress-Ningx Controller
文章目录 一、prometheus中添加ingress-nginx的服务发现配置二、ingress-nginx controller的service添加端口暴露监控指标三、grafana添加ingress-nginx controller的监控模版 ingress-nginx默认是没有开启监控指标的,需要我们在ingress-nginx controller的svc里面开…...
如何在Visual Studio 2019中创建.Net Core WPF工程
如何在Visual Studio 2019中创建.Net Core WPF工程 打开Visual Studio 2019,选择Create a new project 选择WPF App(.Net Core) 输入项目名称和位置,单击Create 这样我们就创建好了一个WPF工程 工程文件说明 Dependencies 当前项目所使用的依赖库&…...
自然语言处理(NLP)论文数量的十年趋势:2014-2024
引言 近年来,自然语言处理(NLP)已成为人工智能(AI)和数据科学领域中的关键技术之一。随着数据规模的不断扩大和计算能力的提升,NLP技术从学术研究走向了广泛的实际应用。通过观察过去十年(2014…...
.net core API中使用LiteDB
LiteDB介绍 LiteDB 是一个小巧、快速和轻量级的 .NET NoSQL 嵌入式数据库。 无服务器的 NoSQL 文档存储简单的 API,类似于 MongoDB100% 的 C# 代码支持 .NET 4.5 / NETStandard 1.3/2.0,以单个 DLL(不到 450KB)形式提供线程安全…...
YOLO_V8分割
YOLO_V8分割 YOLO安装 pip install ultralytics YOLO的数据集转化看csdn 数据标注EIseg EIseg这块,正常安装就好,但是numpy和各类包都容易有冲突,python版本装第一点 数据标注过程中,记得把JSON和COCO都点上,把自…...
根据请求错误的状态码判断代理配置问题
SafeLine,中文名 “雷池”,是一款简单好用, 效果突出的 Web 应用防火墙(WAF),可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注入、命…...
Python 网络爬虫高阶用法
网络爬虫成为了自动化数据抓取的核心工具。Python 拥有强大的第三方库支持,在网络爬虫领域的应用尤为广泛。本文将深入探讨 Python 网络爬虫的高阶用法,包括处理反爬虫机制、动态网页抓取、分布式爬虫以及并发和异步爬虫等技术。以下内容结合最新技术发展…...
芯片Tapeout前GDS Review | Calibre中如何切出gds中指定区域版图?
在SoC芯片实现阶段我们会用到很多模拟IP,IO。对于这类模拟IP相关的电源连接,ESD保护电路连接,信号线连接都需要跟IP Vendor进行Review。但芯片整体版图涉及商业机密,我们不希望整个芯片的版图被各大vendor看到,因此我们…...
43 | 单例模式(下):如何设计实现一个集群环境下的分布式单例模式?
上两篇文章中,我们针对单例模式,讲解了单例的应用场景、几种常见的代码实现和存在的问题,并粗略给出了替换单例模式的方法,比如工厂模式、IOC 容器。今天,我们再进一步扩展延伸一下,一块讨论一下下面这几个…...
PHP如何解决异常处理
在PHP中,异常处理是通过使用try、catch、throw以及finally这几个关键字来实现的。以下是一个简单的介绍和示例: 异常处理的基本步骤 抛出异常: 使用throw关键字抛出一个异常对象。异常对象通常是Exception类或其子类的实例。 捕获异常&…...
C++ socket编程(3)
前面文章,介绍了一个简单socket通讯Demo, 客户端和服务器进行简单的交互。两个代码都很简单,如果情况一复杂,就会出错。这节我们把代码完善一下,实现一个客户端输入,发送,服务器echo的交互。本文…...
Collection-LinkedList源码解析
文章目录 概述LinkedList实现底层数据结构构造函数getFirst(), getLast()removeFirst(), removeLast(), remove(e), remove(index)add()addAll()clear()Positional Access 方法查找操作 概述 LinkedList同时实现了List接口和Deque接口,也就是说它既可以看作一个顺序…...
vue判断对象数组里是否有重复数据
TOCvue判断对象数组里是否有重复数据 try {//通过产品编码赛选出新的数组 在比较let names this.goodsJson.map(item > item["productCode"]);let nameSet new Set(names)if (nameSet.size ! names.length) {this.$message({message: 警告!产品选项…...
CSS 3D转换
在 CSS 中,除了可以对页面中的元素进行 2D 转换外,您也可以对象元素进行 3D转换(将页面看作是一个三维空间来对页面中的元素进行移动、旋转、缩放和倾斜等操作)。与 2D 转换相同,3D 转换同样不会影响周围的元素&#x…...
51单片机数码管循环显示0~f
原理图: #include <reg52.h>sbit dulaP2^6;//段选信号 sbit welaP2^7;//位选信号unsigned char num;//数码管显示的数字0~funsigned char code table[]{ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};//定义数码管显…...
【编程进阶知识】Java NIO:掌握高效的I/O多路复用技术
Java NIO:掌握高效的I/O多路复用技术 摘要: 本文将带你深入了解Java NIO(New I/O)中的Selector类,探索如何利用它实现高效的I/O多路复用,类似于Linux中的select和epoll系统调用。文章将提供详细的代码示例…...
vscode创建flutter项目,运行flutter项目
打开View(查看) > Command Palette...(命令面板)。 可以按下 Ctrl / Cmd Shift P 输入 flutter 选择Flutter: New Project 命令 按下 Enter 。选择Application 选择项目地址 输入项目名称 。按下 Enter 等待项目初始化完成 …...
STM32之CAN外设
相信大家在学习STM32系列的单片机时,在翻阅芯片的数据手册时,都会看到这么一个寄存器外设——CAN外设寄存器。那么,大家知道这个外设的工作原理以及该如何使用吗?这节的内容将会详细介绍STM32上的CAN外设,文章结尾附有…...
【阅读笔记】水果轻微损伤的无损检测技术应用
一、水果轻微损伤检测技术以及应用 无损检测技术顾名思义就是指在不破坏水果样品完整性的情况下对样品进行品质鉴定。目前比较常用的农产品水果类无损检测法有:基于红外热成像、机器视觉技术的图像处理方法、光谱检测技术、介电特性技术检测法等。 1.1 基于红外热…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
