Vue-插槽(slot)

本文详细介绍了Vue中的插槽机制,包括插槽是什么、作用域插槽、后备内容(默认内容)插槽、具名插槽和作用域插槽的用法。通过插槽,父组件可以方便地向子组件传递DOM元素,子组件通过slot标签引用。文中还举例说明了如何使用具名插槽和作用域插槽进行内容定制。

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

在开始讲插槽之前,我们来思考一下:我们都知道,父组件可以随意地向子组件传递一个值,那么问题来了,如果我们要传递一个dom元素,比如说p标签呢?
在这里插入图片描述
这个时候,我们会发现,p标签被转义了,没有直接渲染出来:(
在这里插入图片描述
为了p标签的正常渲染,可以使用v-html,但是与此同时,它外层又会多了一个div标签:
在这里插入图片描述

聪明的童鞋可能想到——用模板占位符template啊!其实在这里它么得用,是渲染不出来的:在这里插入图片描述
害,这也不行,那也不行,那究竟肿么搞嘞??!

当当当当~主角登场——插槽!

1.插槽是什么?

插槽slot,可以通俗地理解成占位符,在组件模板中占好了位置,当使用该组件标签时候,原组件标签的内容(可以是任意的html代码或者其他的组件,比如图标)就会自动替换掉组件模板中的slot。

插槽就是一个萝卜一个坑,子组件挖坑(slot插槽),父组件填萝卜(内容);具名插槽就是把萝卜和坑标了名称,只能对号入座,最后多的无名萝卜进无名的坑(默认插槽),没有无名的坑就丢弃萝卜,坑里有本来就有萝卜那就把萝卜拔出来填父组件的萝卜。

父组件在调用子组件的时候,插入了一个p标签,也就是插槽之中的内容;子组件直接在模板里用slot标签就可以用到父组件传来的p标签了:
在这里插入图片描述
在这里插入图片描述
通过插槽,可以更方便父组件向子组件传递dom元素,子组件使用的时候,通过slot标签进行引用即可。

2.插槽的作用域

插槽跟模板其他地方一样都可以访问相同的实例属性(也就是相同的"作用域"),而不能访问的作用域

<test>
	//插槽可以获取到组件里的内容
	Hello {{word}}
</test>

data(){
	return{
		word:'world!'
	}
}

//这里是获取不到name的,因为其这个值是
  传给<test> 的,而不是在组件*内部*定义的。
<test name='you'>
    Hello {{name}}
</test>

3.后备内容(默认内容)插槽

有时候我们需要给插槽设置一个具体的默认内容,当别的组件没有给你内容的时候,那么默认的内容就会被渲染

//在slot插槽里设置默认内容 Submit
<button>
  <slot>Submit</slot>
</button>

//不提供内容时使用:
<test></test>
//那么最后设置的默认内容 Submit 将会被渲染为:
<button>
   Submit
</button>

//提供内容时使用:
<test>按钮</test>

//那么这个提供的内容将会替代默认的内容被渲染出来:
<button>
   按钮
</button>

4.具名插槽

可以给每个dom标签起名,在子组件里通过“具名插槽”使用不同的插槽内容。有时候我们一个组件里需要多个插槽
对于这样的情况,元素有一个特殊的特性:name ,这个特性可以用来定义额外的插槽

如果一个插槽不带name属性的话,那么它的name默认为default
在向具名插槽提供内容的时候,建议在元素上使用v-slot指令,并以参数的形式提供其名称

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

具名插槽的缩写
2.6.0 新增,与 v-bind v-on 一样,v-slot 使用 # 进行缩写,例如 v-slot:header 可以被重写为 #header 。并且,与前两者一样,指令缩写后面必须接参数,否则无效。

5.作用域插槽

当子组件做循环或者某一部分dom结构需要由外部传递的时候,要用到作用域插槽。

举个栗子:

子组件要实现一个功能——去循环显示一个列表:
(1)那么在子组件里面我定义一组数据,也就是数组list:[1,2,3,4]。
(2)在这个模板里显示一个列表,所以我会写一个ul。然后呢里面去写一个li。循环显示着里标签v-for=“item of list”。
(3)li部分显示item就可以了。
在这里插入图片描述
在这里插入图片描述
组件有可能在很多的地方被调用,那么接下来我有一个需求:
我希望在不同的地方都有child组件的时候,这个列表到底怎么循环,列表的样式不是我这个child组件所控制的,而是父组件告诉子组件:每一项应该如何渲染。

也就是我们的代码把这个li标签要给它去掉,取而代之我们写一个slot。
父组件往子组件传递一个slot,告诉子组件该怎么显示里边的每项:
(1)首先一定要在最外层套一个template,这是一个固定的写法。
(2)同时,你要写一个slot-scope=“props”。这个属性值可以自己随便定义一个。
他的意思是什么呢?当子组件用slot的时候会往slot里面传递一个item数据,那么我们用child的时候就可以用这个item的数据,item就放在你写的slot-scope后面跟的这个属性之中。显示内容通过差值表达式的形式直接写{{props.item}}就行了。
在这里插入图片描述

从头缕一缕思路:
父组件调用子组件时传递了一个(作用域)插槽:

  • 作用域插槽必须是template标签包裹的内容
  • 同时,插槽要声明从子组件接收的数据要放在哪?也就是 slot-scope声明下的“props”里(名称可自定义)
  • 接下来,需要告诉子组件介绍的模板的信息(也就是如何展示) 例如:
    <h1>{{props.item}}</h1>

子组件可以向插槽里面传数据,父组件传如果想接收这个数据,就必须在外层使用一个template,同时通过slot-scope对应的这个属性的名字来接收你传递过来的所有的数据,那这边我传了一个item过来,在父组件的这个作用域插槽里面,我就可以接收到这个item,那我再来使用它就不会有任何的问题啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值