2021-09-12

本文详细介绍了Vue.js中的插槽(Slot)概念,包括匿名插槽、具名插槽和作用域插槽的用法,并通过示例解释了插槽如何实现组件内容的定制和数据传递。插槽主要用于解决组件内部内容插入和重用的问题,使得组件更加模块化和灵活。文章还提供了多个代码示例帮助理解插槽的工作原理和实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是插槽?

插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制

slot官方介绍

Props:

  • name - string,用于命名插槽。

Usage:

  • 元素作为组件模板之中的内容分发插槽。 元素自身将被替换。

官方demo

< slot > 元素

Shadow DOM 使用 元素将不同的 DOM 树组合在一起。Slot 是组件内部的占位符,用户可以使用自己的标记来填充。

通过定义一个或多个 slot,您可将外部标记引入到组件的 shadow DOM 中进行渲染。 这相当于您在说“在此处渲染用户的标记”。

注:Slot 是为网络组件创建“声明性 API”的一种方法。它们混入到用户的 DOM 中,帮助对整个组件进行渲染,从而将不同的 DOM
树组合在一起。

个人理解
slot是对组件的扩展,通过slot插槽向组件内部指定位置传递内容,通过slot可以父子传参;是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中< slot >位置),当插槽也就是坑< slot name=”mySlot”>有命名时,组件标签中使用属性slot=”mySlot”的元素就会替换该对应位置内容;

Slot出现时为了解决什么问题呢?

正常情况下,< Child>< span style=”color:red;”>hello world</ span></ Child>在组件标签Child中的span标签会被组件模板template内容替换掉,当想让组件标签Child中内容传递给组件时需要使用slot插槽;

好多人不知道这个说的是什么?简单讲就是没有一个标志性的标签 < Child>< span style=”color:red;”>hello world</ span></ Child>是不起作用的。 只会显示Child的template的内容,不管template里面还有没有内容,也就是页面上被Child组件模板template内容替换掉了。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Slot</title>
	<style type="text/css">
		.panel{
			width: 400px;
			border: 1px solid #ccc;	
		}
		.panel>*{
			padding: 15px;
			border-bottom: 1px solid #ccc;
		}
		.footer{
			border: none;
		}
	</style>
	<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<Child>
            <span>hello world</span>
        </Child>
	</div>
&lt;template id="child"&gt;
	&lt;div&gt;
		
		&lt;!-- &lt;div class="panel"&gt;
			&lt;div class="title"&gt;这是标题&lt;/div&gt;
			&lt;div class="content"&gt;这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容&lt;/div&gt;
			&lt;div class="footer"&gt;这是页脚&lt;/div&gt;
		&lt;/div&gt; --&gt;
					&lt;div class="panel"&gt;
			&lt;div class="title"&gt;这是标题&lt;/div&gt;
			&lt;div class="content"&gt;这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容&lt;/div&gt;
			&lt;div class="footer"&gt;这是页脚&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/template&gt;

</body>
<script type=“text/javascript”>
new Vue({
el:"#app",
data:{

	},
	components:{
		Child:{
			template:"#child"
		}
	}
})

</script>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

具体怎么使用slot呢?(重点)

事先准备了一个demo

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Slot</title>
	<style type="text/css">
		.panel{
			width: 400px;
			border: 1px solid #ccc;	
		}
		.panel>*{
			padding: 15px;
			border-bottom: 1px solid #ccc;
		}
		.footer{
			border: none;
		}
	</style>
	<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<Child></Child>
	</div>
&lt;template id="child"&gt;
	&lt;div&gt;
		&lt;div class="panel"&gt;
			&lt;div class="title"&gt;这是标题&lt;/div&gt;
			&lt;div class="content"&gt;这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容&lt;/div&gt;
			&lt;div class="footer"&gt;这是页脚&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/template&gt;

</body>
<script type=“text/javascript”>
new Vue({
el:"#app",
data:{

	},
	components:{
		Child:{
			template:"#child"
		}
	}
})

</script>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

在这里插入图片描述

单个或多个匿名插槽

	<div id="app">
		<Child>这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容</Child>
	</div>
&lt;template id="child"&gt;
	&lt;div&gt;
		&lt;div class="panel"&gt;
			&lt;div class="title"&gt;这是标题&lt;/div&gt;
			&lt;div class="content"&gt;
				&lt;slot&gt;&lt;/slot&gt;	
			&lt;/div&gt;
			&lt;div class="footer"&gt;这是页脚&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/template&gt;
结果和初始demo一样,也可以把内容放到slot标签里,不过也就没啥意义了
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
	<div id="app">
		<Child>
			这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容<slot  style="color:red;" >这是在slot上添加了样式</slot>
		</Child>
	</div>
&lt;template id="child"&gt;
	&lt;div&gt;
		&lt;div class="panel"&gt;
			&lt;div class="title"&gt;这是标题&lt;/div&gt;
			&lt;div class="content"&gt;
				&lt;slot&gt;&lt;/slot&gt;
				&lt;slot  style="color:blue;" &gt;这是在slot上添加了样式&lt;/slot&gt;
				&lt;slot name="boboy"&gt;我是boboy&lt;/slot&gt;					
			&lt;/div&gt;
			&lt;div class="footer"&gt;这是页脚&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/template&gt;
结果会输出两遍--这是内容....+这是slot上添加了样式+我是boboy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

注意:只有匿名插槽,若child标签有内容,看模板组件中有几个slot就渲染几次内容, 且slot标签添加样式无效。拥有命名的插槽不能被不含slot属性的标签内容替换,会显示slot的默认值(具名slot具有对应性);

单个或多个具名插槽

	<div id="app">
		<Child>
			<div slot="title">这是页脚</div>
			<div slot="content">这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容</div>
			<div slot="footer">这是页脚</div>
	&lt;/Child&gt;
&lt;/div&gt;

&lt;template id="child"&gt;
	&lt;div&gt;
		&lt;div class="panel"&gt;
			&lt;div class="title"&gt;&lt;slot name="title"&gt;&lt;/slot&gt;&lt;/div&gt;
			&lt;div class="content"&gt;
				&lt;slot name="content"&gt;&lt;/slot&gt;			
			&lt;/div&gt;
			&lt;div class="footer"&gt;&lt;slot name="footer"&gt;&lt;/slot&gt;&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/template&gt;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

作用域插槽
使用时候子组件标签中要有标签,再通过scopeName.childProp就可以调用子组件模板中的childProp绑定的数据,所以作用域插槽是一种子传父传参的方式,解决了普通slot在parent中无法访问child数据的去问题;

作用域插槽代表性的用例是列表组件,允许在parent父组件上对列表项进行自定义显示,如下该items的所有列表项都可以通过slot定义后传递给父组件使用,也就是说数据是相同的,不同的场景页面可以有不同的展示方式,在这就不多展示了,网上很多可供参考。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Slot</title>
	<style type="text/css">
		.panel{
			width: 400px;
			border: 1px solid #ccc;	
		}
		.panel>*{
			padding: 15px;
			border-bottom: 1px solid #ccc;
		}
		.footer{
			border: none;
		}
	</style>
	<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<Child>
			<template slot="content" slot-scope="msg"><div>{
  
  {msg.data}}</div></template>
		</Child>
	</div>
&lt;template id="child" &gt;
	&lt;div&gt;
		&lt;div class="panel"&gt;
			&lt;div class="title"&gt;这是标题&lt;/div&gt;
			&lt;div class="content"&gt;
				&lt;slot name="content" :data="msg"&gt;&lt;/slot&gt;			
			&lt;/div&gt;
			&lt;div class="footer"&gt;这是页脚&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/template&gt;

</body>
<script type=“text/javascript”>
new Vue({
el:"#app",
data:{
},
components:{
Child:{
template:"#child",
data(){
return{
msg:“这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容”
}

			}
		}
	}
})

</script>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

帮助理解:
https://www.jb51.net/article/150676.htm
https://www.jb51.net/article/91976.htm
https://www.jb51.net/article/139214.htm
https://www.jb51.net/article/158639.htm

11-05 188
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值