Vue slot插槽作用与原理深入讲解

 更新时间:2023年01月17日 15:31:23   作者:AI3D_WebEngineer  
插槽slot可以说在一个Vue项目里面处处都有它的身影,比如我们使用一些UI组件库的时候,我们通常可以使用插槽来自定义我们的内容,这篇文章主要介绍了Vue3中slot插槽使用方式,需要的朋友可以参考下

前言

在2.6.0中,具名插槽 和 作用域插槽 引入了一个新的统一的语法 (即v-slot 指令)。它取代了 slot 和 slot-scope。

什么是Slot

当我们生成好组件模板后,为了方便用户在调用组件的时候自定义组件内部分元素的样式或内容。于是在设计组件模板的时候会挖一个坑,等待用户使用v-slot来替换坑的slot位置。

栗子

// father.vue
<template>
  <div>
    <child>
      <h1>AAAA</h1>
    </child>
  </div>
</template>
<template>
  <div>
    <p>这里是子组件哦</p>
    <slot></slot>
  </div>
</template>

可以看见 <h1>AAAA</h1>被 插入到child的里面。

除了可以插入HTML模板代码外,你也可以插入普通文本、其他组件、本组件的数据。

在插槽中使用数据

// father.vue
<template>
  <div>
    <child>
      {{testName}}
      <h1>AAAA</h1>
    </child>
  </div>
</template>
<script>
    ...
    testName = 'Test101';
    ...
</script>

插槽可以使用当前引用子组件的组件数据,但是不能引用传递给子组件的数据。

// father.vue
<template>
  <div>
   <child :childName="testName">
        {{ childName }}
        <h1>AAAA</h1>
    </child>
  </div>
</template>
<script>
    ...
    testName = 'Test101';
    ...
</script>
// child.vue
<template>
  <div>
    <p>这里是子组件{{ childName }}</p>
    <slot></slot>
  </div>
</template>
<script>
import { Component, Vue, Prop } from 'vue-property-decorator';
@Component()
export default class AAChild extends Vue {
  @Prop() childName;
}
</script>

这里是获取不到childName的,因为这个值是传给<child>的

备胎插槽

// father.vue
<div>
   <child :childName="testName"> </child>
</div>
// child.vue
<div>
    <p>这里是子组件{{ childName }}</p>
    <slot> 我是备胎 </slot>
</div>

给插槽设置一个具体的默认内容,当别的组件没有给你内容的时候,那么默认的内容就会被渲染。如果我们提供内容,那么默认的插槽内容会被我们的内容覆盖。

具名插槽

当我们一个组件里需要定义多个插槽时,需要使用slot元素的特性name来定义额外的插槽。

// child.vue
<template>
  <div>
    <p>插槽一的位置</p>
    <slot name="slot1"> </slot>
    <p>------------------------</p>
    <p>插槽二的位置</p>
    <slot> </slot>
    <p>------------------------</p>
    <p>插槽三的位置</p>
    <slot name="slot3"> </slot>
  </div>
</template>
// father.vue
 <child>
    <template v-slot:slot1>
      <h1>slotOne</h1>
    </template>
    <template>
     <h1>slotTwo</h1> 
    </template>
    <template v-slot:slot3> 
        <h1>slotThree</h1> 
    </template>
</child>

如果一个<slot>不带name属性的话,那么它的name默认为default,可以不用v-slot去指定它。(如果你非要折腾,也可以写name="default")

在向具名插槽提供内容的时候,我们可以在<template>元素上使用v-slot指令,并以参数的形式提供其名称。

注:v-slot只能添加在一个<template>上,(只有一种例外情况,下面会说)

覆盖问题

当存在同名的v-slot的时候,后面会覆盖前面的。

当存在两个匿名的插槽的时候,两者都会被丢进去默认插槽里。

只更改了father.vue

// father.vue
 <child>
        <template v-slot:slot1>
          <h1>slotOne</h1>
        </template>
        <template> <h1>slotTwo</h1> </template>
        <template v-slot:slot3> <h1>slotThree</h1> </template>
        <template v-slot:slot3> <h1>slotThreeAAAAAAAAA</h1> </template>
        <template> <h1>slotTwoAAAAAAAAAAAA</h1> </template>
</child>

作用域插槽

插槽跟模板其他地方一样都可以访问当前father组件的作用域而不能访问<child>的作用域

如果要访问child的作用域该怎么办呢?

// child.vue
<template>
  <div>
    <p>下面有一个插槽</p>
    <slot :aName="name"></slot>
  </div>
</template>
<script>
import { Component, Vue, Prop } from 'vue-property-decorator';
@Component()
export default class AAChild extends Vue {
  name = '123';
}
</script>
// father.vue
<template>
    <div>
     <child>
        <template v-slot:default="slotProps">
          <h1>{{ slotProps.aName }}</h1>
        </template>
      </child>
    </div>
</template>

v-slot:default="slotProps"接住了child组件里在slot元素上绑定的作用域属性,同时吧template只想了默认插槽。

具名插槽的作用域

// father.vue
<template>
    <div>
      <child>
        <template v-slot:default="slotProps">
          <h1>{{ slotProps.aName }}</h1>
        </template>
        <template v-slot:slotA="slotProps">
          <h1>{{ slotProps.nameA }}</h1>
        </template>
      </child>
    </div>
</template>
// child.vue
<template>
  <div>
    <p>下面有一个插槽</p>
    <slot :aName="name"></slot>
    <slot :nameA="nameA" name="slotA"></slot>
  </div>
</template>
<script>
import { Component, Vue, Prop } from 'vue-property-decorator';
@Component()
export default class AAChild extends Vue {
  name = '123';
  nameA = '321';
}
</script>

过时的写法:

<template slot="custom" slot-scope="item"></template >

现在的写法:

<template v-slot:custom="{item}"></template >

解构插槽Prop

v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JS 表达式(作用域插槽 的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里)

// child.vue
<template>
  <div>
    <p>下面有一个插槽</p>
    <slot :nameData="nameObj"></slot>
  </div>
</template>
<script>
import { Component, Vue, Prop } from 'vue-property-decorator';
@Component()
export default class AAChild extends Vue {
  nameObj = {
    name: '插槽君',
    key: '202203241567',
  };
}
</script>
// father.vue
<template>
    <div>
      <child>
        <template v-slot="slotProps">
          <h1>{{ slotProps.nameData.name }}</h1>
        </template>
      </child>
    </div>
</template>

father,vue可以改写为

// father.vue
<template>
    <div>
      <child>
        <template v-slot="{ nameData }">
          <h1>{{ nameData.name }}</h1>
        </template>
      </child>
    </div>
</template>

这样可以使模板更简洁。

具名插槽的缩写

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header:

// father.vue
<template>
    <div>
      <child>
        <template v-slot:keyDDD="{ nameData }">
          <h1>{{ nameData.name }}</h1>
        </template>
      </child>
    </div>
</template>

等同于

// father.vue
<template>
    <div>
      <child>
        <template #keyDDD="{ nameData }">
          <h1>{{ nameData.name }}</h1>
        </template>
      </child>
    </div>
</template>

$scopedSlots

和slot-scope 的区别?

  • 作用相同:都是作用域插槽
  • 场景不同:slot-scope 是模板语法,scopedSlots 则是编程式语法
  • 使用不同:在 <template> 中使用 slot-scope,在 render() 函数中使用 scopedSlots
<template v-if="$scopedSlots.label" v-slot:title="{ data }">
     <slot name="label" :data="data" > </slot>
</template>

或者

  render() {
    return this.$scopedSlots.default
      ? this.$scopedSlots.default(this.title)
      : null;
  }

到此这篇关于Vue slot插槽作用与原理深入讲解的文章就介绍到这了,更多相关Vue slot插槽内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue之封装多个组件调用同一接口的案例

    vue之封装多个组件调用同一接口的案例

    这篇文章主要介绍了vue之封装多个组件调用同一接口的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • vue+element+electron仿微信实现代码

    vue+element+electron仿微信实现代码

    这篇文章主要介绍了vue+element+electron仿微信实现,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • Vue中v-for的数据分组实例

    Vue中v-for的数据分组实例

    下面小编就为大家分享一篇Vue中v-for的数据分组实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • vue路由$router.push()使用query传参的实际开发使用

    vue路由$router.push()使用query传参的实际开发使用

    在vue项目中我们用函数式编程this.$router.push跳转,用query传递一个对象时要把这个对象先转化为字符串,然后在接收的时候要转化为对象,下面这篇文章主要给大家介绍了关于vue路由$router.push()使用query传参的实际开发使用,需要的朋友可以参考下
    2022-11-11
  • vue+elementUI实现多文件上传与预览功能实战记录(word/PDF/图片/docx/doc/xlxs/txt)

    vue+elementUI实现多文件上传与预览功能实战记录(word/PDF/图片/docx/doc/xlxs/txt)

    这篇文章主要给大家介绍了关于利用vue+elementUI实现多文件上传与预览功能的相关资料,包括word/PDF/图片/docx/doc/xlxs/txt等格式文件上传,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • 使用VUE实现一键复制内容功能

    使用VUE实现一键复制内容功能

    这篇文章主要介绍了使用VUE实现一键复制内容功能,功能就是当我们点击复制按钮时,会提示“复制成功”,这样复制的内容就可以在其他地方使用了,感兴趣的朋友可以学习一下
    2023-04-04
  • vue内点击url下载文件的最佳解决方案分享

    vue内点击url下载文件的最佳解决方案分享

    这篇文章主要给大家介绍了关于vue内点击url下载文件的最佳解决方案,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-02-02
  • Vue3 $emit用法指南(含选项API、组合API及 setup 语法糖)

    Vue3 $emit用法指南(含选项API、组合API及 setup 语法糖)

    这篇文章主要介绍了Vue3 $emit用法指南,使用 emit,我们可以触发事件并将数据传递到组件的层次结构中,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • vue中的自定义指令clickOutside

    vue中的自定义指令clickOutside

    这篇文章主要介绍了vue中的自定义指令clickOutside,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • 详解VUE项目中安装和使用vant组件

    详解VUE项目中安装和使用vant组件

    这篇文章主要介绍了VUE安装和使用vant组件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04

最新评论