Vue2基础八、插槽
零、文章目录
Vue2基础八、插槽
1、插槽
(1)默认插槽
- 作用:让组件内部的一些 结构 支持 自定义
- 需求: 将需要多次显示的对话框, 封装成一个组件
- 问题:组件的内容部分,不希望写死,希望能使用的时候自定义。怎么办?

- 插槽基本语法:
- 组件内需要定制的结构部分,改用
<slot></slot>占位 - 使用组件时,
<MyDialog></MyDialog>标签内部, 传入结构替换slot
- 组件内需要定制的结构部分,改用

-
代码实现
- 父组件
App.vue
<template><div><!-- 2. 在使用组件时,组件标签内填入内容 --><MyDialog><div>你确认要删除么</div></MyDialog><MyDialog><p>你确认要退出么</p></MyDialog></div> </template><script> import MyDialog from './components/MyDialog.vue' export default {data () {return {}},components: {MyDialog} } </script><style> body {background-color: #b3b3b3; } </style>- 子组件
MyDialog.vue
<template><div class="dialog"><div class="dialog-header"><h3>友情提示</h3><span class="close">✖️</span></div><div class="dialog-content"><!-- 1. 在需要定制的位置,使用slot占位 --><slot></slot></div><div class="dialog-footer"><button>取消</button><button>确认</button></div></div> </template><script> export default {data () {return {}} } </script><style scoped> * {margin: 0;padding: 0; } .dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px; } .dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative; } .dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer; } .dialog-content {height: 80px;font-size: 18px;padding: 15px 0; } .dialog-footer {display: flex;justify-content: flex-end; } .dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px; } .dialog-footer button:last-child {background-color: #007acc;color: #fff; } </style> - 父组件
(2)后备内容(默认值)
- 通过插槽完成了内容的定制,传什么显示什么, 但是如果不传,则是空白
- 能否给插槽设置
默认显示内容呢?

-
插槽后备内容:封装组件时,可以为预留的
<slot>插槽提供后备内容(默认内容)。 -
语法: 在
<slot>标签内,放置内容作为默认内容,<slot>后备内容</slot>-
外部使用组件时,不传东西,则slot会显示后备内容
<MyDialog></MyDialog> -
外部使用组件时,传东西了,则slot整体会被换掉
<MyDialog>我是内容</MyDialog> -
-
代码实现
- 父组件
App.vue
<template><div><MyDialog></MyDialog><MyDialog>你确认要退出么</MyDialog></div> </template><script> import MyDialog from './components/MyDialog.vue' export default {data () {return {}},components: {MyDialog} } </script><style> body {background-color: #b3b3b3; } </style>- 子组件
MyDialog.vue
<template><div class="dialog"><div class="dialog-header"><h3>友情提示</h3><span class="close">✖️</span></div><div class="dialog-content"><!-- 往slot标签内部,编写内容,可以作为后备内容(默认值) --><slot>我是默认的文本内容</slot></div><div class="dialog-footer"><button>取消</button><button>确认</button></div></div> </template><script> export default {data () {return {}} } </script><style scoped> * {margin: 0;padding: 0; } .dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px; } .dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative; } .dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer; } .dialog-content {height: 80px;font-size: 18px;padding: 15px 0; } .dialog-footer {display: flex;justify-content: flex-end; } .dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px; } .dialog-footer button:last-child {background-color: #007acc;color: #fff; } </style> - 父组件
(3)具名插槽
- 需求:一个组件内有多处结构,需要外部传入标签,进行定制
- 默认插槽:一个的定制位置

- 具名插槽语法:
- 多个slot使用name属性区分名字
- template配合
v-slot:名字来分发对应标签 v-slot:插槽名可以简化成#插槽名

-
代码实现:
- 父组件
App.vue
<template><div><MyDialog><!-- 需要通过template标签包裹需要分发的结构,包成一个整体 --><template v-slot:head><div>我是大标题</div></template><template v-slot:content><div>我是内容</div></template><template #footer><button>取消</button><button>确认</button></template></MyDialog></div> </template><script> import MyDialog from './components/MyDialog.vue' export default {data () {return {}},components: {MyDialog} } </script><style> body {background-color: #b3b3b3; } </style>- 子组件
MyDialog.vue
<template><div class="dialog"><div class="dialog-header"><!-- 一旦插槽起了名字,就是具名插槽,只支持定向分发 --><slot name="head"></slot></div><div class="dialog-content"><slot name="content"></slot></div><div class="dialog-footer"><slot name="footer"></slot></div></div> </template><script> export default {data () {return {}} } </script><style scoped> * {margin: 0;padding: 0; } .dialog {width: 470px;height: 230px;padding: 0 25px;background-color: #ffffff;margin: 40px auto;border-radius: 5px; } .dialog-header {height: 70px;line-height: 70px;font-size: 20px;border-bottom: 1px solid #ccc;position: relative; } .dialog-header .close {position: absolute;right: 0px;top: 0px;cursor: pointer; } .dialog-content {height: 80px;font-size: 18px;padding: 15px 0; } .dialog-footer {display: flex;justify-content: flex-end; } .dialog-footer button {width: 65px;height: 35px;background-color: #ffffff;border: 1px solid #e1e3e9;cursor: pointer;outline: none;margin-left: 10px;border-radius: 3px; } .dialog-footer button:last-child {background-color: #007acc;color: #fff; } </style> - 父组件
(4)作用域插槽
-
作用域插槽: 定义 slot 插槽的同时, 是可以
传值的。给插槽上可以 绑定数据,将来使用组件时可以用。 -
场景:封装表格组件
- 父传子,动态渲染表格内容
- 利用默认插槽,定制操作列
- 删除或查看都需要用到
当前项的 id,属于组件内部的数据通过作用域插槽传值绑定,进而使用

-
基本使用步骤:
- 给 slot 标签, 以 添加属性的方式传值
<slot :id="item.id" msg="测试文本"></slot>- 所有添加的属性, 都会被收集到一个对象中
{ id: 3, msg: '测试文本' }- 在template中, 通过
#插槽名= "obj"接收,默认插槽名为default
<MyTable :list="list"><template #default="obj"><button @click="del(obj.id)">删除</button></template> </MyTable> -
代码实现
- 父组件
App.vue
<template><div><MyTable :data="list"><!-- 3. 通过template #插槽名="变量名" 接收 --><template #default="obj"><button @click="del(obj.row.id)">删除</button></template></MyTable><MyTable :data="list2"><template #default="{ row }"><button @click="show(row)">查看</button></template></MyTable></div> </template><script> import MyTable from './components/MyTable.vue' export default {data () {return {list: [{ id: 1, name: '张小花', age: 18 },{ id: 2, name: '孙大明', age: 19 },{ id: 3, name: '刘德忠', age: 17 },],list2: [{ id: 1, name: '赵小云', age: 18 },{ id: 2, name: '刘蓓蓓', age: 19 },{ id: 3, name: '姜肖泰', age: 17 },]}},methods: {del (id) {this.list = this.list.filter(item => item.id !== id)},show (row) {// console.log(row);alert(`姓名:${row.name}; 年纪:${row.age}`)}},components: {MyTable} } </script>- 子组件
MyTable.vue
<template><table class="my-table"><thead><tr><th>序号</th><th>姓名</th><th>年纪</th><th>操作</th></tr></thead><tbody><tr v-for="(item, index) in data" :key="item.id"><td>{{ index + 1 }}</td><td>{{ item.name }}</td><td>{{ item.age }}</td><td><!-- 1. 给slot标签,添加属性的方式传值 --><slot :row="item" msg="测试文本"></slot><!-- 2. 将所有的属性,添加到一个对象中 --><!-- {row: { id: 2, name: '孙大明', age: 19 },msg: '测试文本'}--></td></tr></tbody></table> </template><script> export default {props: {data: Array} } </script><style scoped> .my-table {width: 450px;text-align: center;border: 1px solid #ccc;font-size: 24px;margin: 30px auto; } .my-table thead {background-color: #1f74ff;color: #fff; } .my-table thead th {font-weight: normal; } .my-table thead tr {line-height: 40px; } .my-table th, .my-table td {border-bottom: 1px solid #ccc;border-right: 1px solid #ccc; } .my-table td:last-child {border-right: none; } .my-table tr:last-child td {border-bottom: none; } .my-table button {width: 65px;height: 35px;font-size: 18px;border: 1px solid #ccc;outline: none;border-radius: 3px;cursor: pointer;background-color: #ffffff;margin-left: 5px; } </style> - 父组件
2、综合案例-商品列表
(1)功能需求
- my-tag 标签组件封装
- (1) 双击显示输入框,输入框获取焦点
- (2) 失去焦点,隐藏输入框
- (3) 回显标签信息
- (4) 内容修改,回车 → 修改标签信息
- my-table 表格组件封装
- (1) 动态传递表格数据渲染
- (2) 表头支持用户自定义
- (3) 主体支持用户自定义

(2)代码实现
- 父组件
App.vue
<template><div class="table-case"><MyTable :data="goods"><template #head><th>编号</th><th>名称</th><th>图片</th><th width="100px">标签</th></template><template #body="{ item, index }"><td>{{ index + 1 }}</td><td>{{ item.name }}</td><td><img:src="item.picture"/></td><td><MyTag v-model="item.tag"></MyTag></td></template></MyTable></div>
</template><script>
// my-tag 标签组件的封装
// 1. 创建组件 - 初始化
// 2. 实现功能
// (1) 双击显示,并且自动聚焦
// v-if v-else @dbclick 操作 isEdit
// 自动聚焦:
// 1. $nextTick => $refs 获取到dom,进行focus获取焦点
// 2. 封装v-focus指令// (2) 失去焦点,隐藏输入框
// @blur 操作 isEdit 即可// (3) 回显标签信息
// 回显的标签信息是父组件传递过来的
// v-model实现功能 (简化代码) v-model => :value 和 @input
// 组件内部通过props接收, :value设置给输入框// (4) 内容修改了,回车 => 修改标签信息
// @keyup.enter, 触发事件 $emit('input', e.target.value)// ---------------------------------------------------------------------// my-table 表格组件的封装
// 1. 数据不能写死,动态传递表格渲染的数据 props
// 2. 结构不能写死 - 多处结构自定义 【具名插槽】
// (1) 表头支持自定义
// (2) 主体支持自定义import MyTag from './components/MyTag.vue'
import MyTable from './components/MyTable.vue'
export default {name: 'TableCase',components: {MyTag,MyTable},data () {return {// 测试组件功能的临时数据tempText: '水杯',tempText2: '钢笔',goods: [{ id: 101, picture: './assets/img/news.png', name: '梨皮朱泥三绝清代小品壶经典款紫砂壶', tag: '茶具' },{ id: 102, picture: './assets/img/news.png', name: '全防水HABU旋钮牛皮户外徒步鞋山宁泰抗菌', tag: '男鞋' },{ id: 103, picture: './assets/img/news.png', name: '毛茸茸小熊出没,儿童羊羔绒背心73-90cm', tag: '儿童服饰' },{ id: 104, picture: './assets/img/news.png', name: '基础百搭,儿童套头针织毛衣1-9岁', tag: '儿童服饰' },]}}
}
</script><style lang="less" scoped>
.table-case {width: 1000px;margin: 50px auto;img {width: 100px;height: 100px;object-fit: contain;vertical-align: middle;}
}</style>
- 子组件
MyTable.vue
<template><table class="my-table"><thead><tr><slot name="head"></slot></tr></thead><tbody><tr v-for="(item, index) in data" :key="item.id"><slot name="body" :item="item" :index="index" ></slot></tr></tbody></table>
</template><script>
export default {props: {data: {type: Array,required: true}}
};
</script><style lang="less" scoped>
.my-table {width: 100%;border-spacing: 0;img {width: 100px;height: 100px;object-fit: contain;vertical-align: middle;}th {background: #f5f5f5;border-bottom: 2px solid #069;}td {border-bottom: 1px dashed #ccc;}td,th {text-align: center;padding: 10px;transition: all .5s;&.red {color: red;}}.none {height: 100px;line-height: 100px;color: #999;}
}
</style>
- 子组件
MyTag.vue
<template><div class="my-tag"><inputv-if="isEdit"v-focusref="inp"class="input"type="text"placeholder="输入标签":value="value"@blur="isEdit = false"@keyup.enter="handleEnter"/><div v-else@dblclick="handleClick"class="text">{{ value }}</div></div>
</template><script>
export default {props: {value: String},data () {return {isEdit: false}},methods: {handleClick () {// 双击后,切换到显示状态 (Vue是异步dom更新)this.isEdit = true// // 等dom更新完了,再获取焦点// this.$nextTick(() => {// // 立刻获取焦点// this.$refs.inp.focus()// })},handleEnter (e) {// 非空处理if (e.target.value.trim() === '') return alert('标签内容不能为空')// 子传父,将回车时,[输入框的内容] 提交给父组件更新// 由于父组件是v-model,触发事件,需要触发 input 事件this.$emit('input', e.target.value)// 提交完成,关闭输入状态this.isEdit = false}}
}
</script><style lang="less" scoped>
.my-tag {cursor: pointer;.input {appearance: none;outline: none;border: 1px solid #ccc;width: 100px;height: 40px;box-sizing: border-box;padding: 10px;color: #666;&::placeholder {color: #666;}}
}
</style>
- 入口
main.js注册自定义指令
import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = false// 封装全局指令 focus
Vue.directive('focus', {// 指令所在的dom元素,被插入到页面中时触发inserted (el) {el.focus()}
})new Vue({render: h => h(App),
}).$mount('#app')
相关文章:
Vue2基础八、插槽
零、文章目录 Vue2基础八、插槽 1、插槽 (1)默认插槽 作用:让组件内部的一些 结构 支持 自定义需求: 将需要多次显示的对话框, 封装成一个组件问题:组件的内容部分,不希望写死,希望能使用的时候自定义。…...
自然语言处理从入门到应用——LangChain:提示(Prompts)-[提示模板:连接到特征存储]
分类目录:《自然语言处理从入门到应用》总目录 特征存储是传统机器学习中的一个概念,它确保输入模型的数据是最新和相关的。在考虑将LLM应用程序投入生产时,这个概念非常重要。为了个性化LLM应用程序,我们可能希望将LLM与特定用户…...
jenkins自定义邮件发送人姓名
jenkins发送邮件的时候发送人姓名默认的,如果要自定义发件人姓名,只需要修改如下信息即可: 系统管理-system-Jenkins Location下的系统管理员邮件地址 格式为:自定义姓名<邮件地址>...
SolidWorks二次开发---简单的连接solidworks
创建一个.net Framework的应用,正常4.0以上就可以了。 打开nuget包管理 在里面搜索paine 在版中选择对应的solidworks年份开头的,进行安装。 安装完之后 : 同时选中下面两个dll,把嵌入操作类型改为false 然后在按钮的单击事件中输入: Connect.Crea…...
docker 安装 active Mq
在安装完Docker的机器上,安装activeMQ。 拉取镜像: docker pull webcenter/activemq 查看镜像: docker images Docker运行ActiveMQ镜像 docker run --name activemq -d -p 8161:8161 -p 61616:61616 --privilegedtrue --restartalways …...
【Linux】TCP协议
🌠 作者:阿亮joy. 🎆专栏:《学会Linux》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录 👉TCP协议&…...
DevOps系列文章之 自动化测试大全(单测和集成测试)
自动化测试业界主流工具 核心目标: 主要是功能测试和覆盖率测试 业界常用主流工具 GoogleTest GoogleTest是一个跨平台的(Liunx、Mac OS X、Windows 、Cygwin 、Windows CE and Symbian ) C单元测试框架,由google公司发布,为在不同平台上为编…...
Android启动速度优化
本节主要内容:了解APP启动流程、启动状态、查看启动时间、CPU Profile定位启动耗时代码、StrictMode严苛模式检测不合理写法、解决启动黑白屏问题。 一、APP启动流程 ①用户点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startAc…...
linux 日志 系统安全日志 web日志
web日志 LINUX日志系统之WEB日志(一)_dracut.log_麻子来了的博客-CSDN博客 系统安全日志 Linux系统安全日志详解_sinolover的博客-CSDN博客 wtmp和utmp文件都是二进制文件,需使用who、w、users、last和ac来操作这两个文件。 who /var/lo…...
SpringBoot 整合 MongoDB 连接 阿里云MongoDB
注:spring-boot-starter-data-mongodb 2.7.5;jdk 1.8 阿里云MongoDB是副本集实例的 在网上查找了一番,大多数都是教连接本地mongodb或者linux上的mongodb 阿里云上有java版连接教程,但它不是SpringBoot方法配置的,是手…...
Debeizum 增量快照
在Debeizum1.6版本发布之后,成功推出了Incremental Snapshot(增量快照)的功能,同时取代了原有的实验性的Parallel Snapshot(并行快照)。在本篇博客中,我将介绍全新快照方式的原理,以…...
windows下安装composer
安装Php 教程 下载composer 官网 中文网站 exe下载地址 下载好exe 双击运行 找到php.ini注释一行代码 测试 composer -v说明安装成功 修改源 执行以下命令即可修改 composer config -g repo.packagist composer https://packagist.phpcomposer.com # 查看配置…...
企业游学进华秋,助力电子产业创新与发展
近日,淘IC企业游学活动,携20多位电子行业的企业家,走进了深圳华秋电子有限公司(以下简称“华秋”),进行交流学习、供需对接。华秋董事长兼CEO陈遂佰对华秋的发展历程、业务版块、产业布局等做了详尽的介绍&…...
玩转Tomcat:从安装到部署
文章目录 一、什么是 Tomcat二、Tomcat 的安装与使用2.1 下载安装2.2 目录结构2.3 启动 Tomcat 三、部署程序到 Tomcat3.1 Windows环境3.2 Linux环境 一、什么是 Tomcat 一看到 Tomcat,我们一般会想到什么?没错,就是他,童年的回忆…...
吃透《西瓜书》第四章 决策树定义与构造、ID3决策树、C4.5决策树、CART决策树
目录 一、基本概念 1.1 什么是信息熵? 1.2 决策树的定义与构造 二、决策树算法 2.1 ID3 决策树 2.2 C4.5 决策树 2.3 CART 决策树 一、基本概念 1.1 什么是信息熵? 信息熵: 熵是度量样本集合纯度最常用的一种指标,代表一个系统中蕴…...
复现宏景eHR存在任意文件上传漏洞(0day)
目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现 一、漏洞描述 北京宏景世纪软件股份有限公司(简称“宏景软件”)自成立以来始终专注于国有企事业单位人力与人才管理数智化(数字化、智能化)产品的研发和应用推广,是中国国有企事业单位人力与人才管理数智…...
unity连接MySQL数据库并完成增删改查
数据存储量比较大时,我就需要将数据存储在数据库中方便使用,尤其是制作管理系统时,它的用处就更大了。 在编写程序前,需要在Assets文件夹中创建plugins文件,将.dll文件导入,文件从百度网盘自取:…...
13个ChatGPT类实用AI工具汇总
在ChatGPT爆火后,各种工具如同雨后春笋一般层出不穷。以下汇总了13种ChatGPT类实用工具,可以帮助学习、教学和科研。 01 / ChatGPT for google/ 一个浏览器插件,可搭配现有的搜索引擎来使用 最大化搜索效率,对搜索体验的提升相…...
1-linux下mysql8.0.33安装
在互联网企业的日常工作/运维中,我们会经常用到mysql数据库,而linux下mysql的安装方式有三种: 1.mysql rpm安装 2.mysql二进制安装 3.mysql源码安装 今天就为大家讲讲linux下mysql8.0.33版本rpm方式的安装。 1.前提 1.1.系统版本 Cent…...
golang反射获取结构体的值和修改值
功能:根据id和反射技术封装 创建和更新人的查询 一、代码二、演示 一、代码 package coryCommonimport ("context""errors""github.com/gogf/gf/v2/container/gvar""github.com/tiger1103/gfast/v3/internal/app/system/dao&qu…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
