前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VUE作用域插槽详解(<slot>、v-slot、slot-scope)「建议收藏」

VUE作用域插槽详解(<slot>、v-slot、slot-scope)「建议收藏」

作者头像
全栈程序员站长
发布2022-07-29 12:59:22
12.1K0
发布2022-07-29 12:59:22
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

什么是插槽?

插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。插槽显不显示怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制

如下代码:

  1. 在子组件中放一个占位符
  1. 在父组件中给这个占位符填充内容:
  1. 展示的效果:

现在来看看,如果子组件中没有放插槽,同样的父组件中在子组件中填充内容,会是啥样的:

  1. 子组件代码无插槽:

2. 父组件照常填充内容:

3. 展示的效果:

总结:如果子组件没有使用插槽,父组件如果需要往子组件中填充模板或者html, 是没法做到的

插槽的使用

插槽的最最简单使用,上面已有例子,这里就不写了,接下来看看,插槽其他使用场景。

插槽的使用 – 具名插槽

描述:具名插槽其实就是给插槽娶个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。

如下代码:

  1. 子组件的代码,设置了两个插槽(header和footer):
  1. 父组件填充内容, 父组件通过 v-slot:[name] 的方式指定到对应的插槽中

3.展示的效果:

接下来再来看看,父组件中填充内容的时候,顺序调换下,看下能不能内容能不能对应上:

  1. 子组件代码不变,父组件代码中填充顺序调换下(如图,在父组件中,footer 和 header 的填充位置对换):
  1. 展示的效果:

由此看出,即使父组件对插槽的填充的顺序打乱,只要名字对应上了,就可以正确渲染到对应的插槽中。 父组件填充内容时,是可以根据这个名字把内容填充到对应插槽中的

总之,slot存在于子组件,v-slot在父组件,最终页面展示结果是父组件!!!

插槽的使用 – 默认插槽

描述: 默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。

示例代码如下: 1.子组件代码定义了一个默认插槽:

2.父组件给默认插槽填充内容:

3. 展现的内容

注意:

1. 父级的填充内容如果指定到子组件的没有对应名字插槽,那么该内容不会被填充到默认插槽中。即具名插槽用name属性来表示插槽的名字,不传为默认插槽

2. 如果子组件没有默认插槽,而父级的填充内容指定到默认插槽中,那么该内容就不会填充到子组件的任何一个插槽中。

3. 如果子组件有多个默认插槽,而父组件所有指定到默认插槽的填充内容,将会且全都填充到子组件的每个默认插槽中。

插槽的使用 – 作用域插槽

作用域插槽的概念和使用比较难于理解,通过查看多方资料,做了以下的总结: 描述:作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。

使用方法: 1.子组件存放一个带数据的插槽,代码如下:

代码语言:javascript
复制
<template>
  <div class="child">

    <h3>这里是子组件</h3>
    <slot  :data="data"></slot>
  </div>
</template>

 export default {
    data: function(){
      return {
        data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
    }
}

2.父组件通过 “slot-scope” 来接收子组件传过来的插槽数据,再根据插槽数据来填充插槽的内容

代码语言:javascript
复制
<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <!--第一次使用:用flex展示数据:  class="tmpl"-->
    <child>
      <template slot-scope="user">
        <div class="tmpl">
          <span v-for="item in user.data">{
  
  {item}}</span>
        </div>
      </template>

    </child>

    <!--第二次使用:用列表展示数据-->
    <child>
      <template slot-scope="user">
        <ul>
          <li v-for="item in user.data">{
  
  {item}}</li>
        </ul>
      </template>

    </child>

    <!--第三次使用:直接显示数据-->
    <child>
      <template slot-scope="user">
       {
  
  {user.data}}
      </template>

    </child>

    <!--第四次使用:不使用其提供的数据, 作用域插槽退变成匿名插槽-->
    <child>
      我就是模板
    </child>
  </div>
</template>

3.展现的效果:

作用域插槽绑定了一套数据,父组件可以拿来用。于是,情况就变成了这样:样式父组件说了算,但内容可以显示子组件插槽绑定的。 我们再来对比,作用域插槽跟单个插槽和具名插槽的区别,因为单个插槽和具名插槽不绑定数据,所以父组件提供的模板一般要既包括样式又包括内容,而作用域插槽,父组件只需要提供一套样式(在确实用作用域插槽绑定的数据的前提下)。 上面的例子,你就能看到,父组件提供了三种样式(分别是flex、ul、直接显示),都没有提供数据,数据使用的都是子组件插槽自己绑定的那个数组(一堆人名的那个数组)。

4.常用场景(以下为常用的情况之一) 如果子组件中的某一部分的数据,每个父组件都会有自己的一套对该数据的不同的呈现方式,这时就需要用到作用域插槽。

再来个例子加深印象

slot的用法可以分为三类,分别是默认插槽、具名插槽、作用域插槽

子组件中:

  • 插槽用 <slot> 标签来确定渲染的位置,里面放如果父组件没传内容时的后备内容
  • 具名插槽name属性来表示插槽的名字,不传为默认插槽
  • 作用域插槽在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件slot-scope接收的对象上
代码语言:javascript
复制
//Child.vue
<template>
	<div>
		<main>
		//默认插槽
			<slot>
				//slot内为后备内容
				<h3>没传内容</h3>
			</slot>
		</main>
		
		//具名插槽
		<header>
			<slot name="header">
				<h3>没传header插槽</h3>
			</slot>
		</header>

		//作用域插槽
		<footer>
			<slot name="footer" testProps="子组件的值">
			 <h3>没传footer插槽</h3> 
			</slot> 
		</footer>
	</div>
</template>

<style scoped>
div{
	border:1px solid #000;
}
</style>

父组件在使用时:

  • 默认插槽的话直接在子组件的标签内写入内容即可
  • 具名插槽是在默认插槽的基础上加上slot属性,值为子组件插槽name属性值
  • 作用域插槽则是通过slot-scope获取子组件的信息,在内容中使用。这里可以用解构语法去直接获取想要的属性
代码语言:javascript
复制
// Parent.vue
<child>
  <!-- 默认插槽 -->
  <div>默认插槽</div>  
  <!-- 具名插槽 -->
  <div slot="header">具名插槽header</div>
  <!-- 作用域插槽 -->
  <div slot="footer" slot-scope="slotProps">
    {
  
  {slotProps.testProps}}
  </div>
</child>

渲染结果为

v-slot

在vue2.6中。上述的API被软废弃(3.0正式废弃),取而代之的是内置指令v-slot,可以缩写为【#】

子组件用法保持不变,父组件中
  • slot属性弃用,具名插槽通过指令参数v-slot:插槽名的形式传入,可以简化为#插槽名
  • slot-scope属性弃用,作用域插槽通过v-slot:xxx="slotProps"的slotProps来获取子组件传出的属性
  • v-slot属性只能在template上使用,但在只有默认插槽时可以在组件标签上使用
代码语言:javascript
复制
//Parent
<template>
  <child>
   <!--默认插槽-->
   <template v-slot>
     <div>默认插槽</div>
   </template>
   <!--具名插槽-->
   <template #header>
     <div>具名插槽</div>
   </template>
   <!--作用域插槽-->
   <template #footer="slotProps">
     <div>
      {
  
  {slotProps.testProps}}
     </div>
   </template>
  <child>
</template>
拓展用法:
  1. 同样可以通过解构获取v-slot={user},还可以重命名v-slot="{user:newName}"和定义默认值v-slot="{user = '默认值'}"
  2. 插槽名可以是动态变化的v-slot:[slotName]
注意

1.默认插槽名为default,可以省略default直接写v-slot,缩写为#时不能不写参数,写成#default(这点所有指令都一样,v-bind、v-on) 2.多个插槽混用时,v-slot不能省略default

作用域插槽的原理

slot本质上是返回VNode的函数,一般情况下,Vue中的组件要渲染到页面上需要经过template>>render function >> NVode >> DOM过程。组件挂载的本质就是执行渲染函数得到VNode,至于data/props/computed这些属性都是给VNode提供数据来源

在2.5之前,如果是普通插槽就直接是VNode的形式了,而如果是作用域插槽,由于子组件需要再父组件访问子组件的数据,所以父组件下是一个未执行的函数(slotScopre) => return h('div',slotScope.msg),接受子组件的slotProps参数,在子组件渲染实例时会调用该函数传入数据。

在2.6之后,两者合并,普通插槽也变成一个函数,只是不接受参数了

因为第二篇文章有些新的可取之处,所以又整合了这篇文章加深理解,原文链接:https://blog.csdn.net/H_c_l/article/details/100151287

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/129203.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年4月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是插槽?
  • 插槽的使用
    • 插槽的使用 – 具名插槽
      • 插槽的使用 – 默认插槽
        • 插槽的使用 – 作用域插槽
          • 再来个例子加深印象
            • 父组件在使用时:
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档