你使用的Vue插槽(slot)语法可能已经过时了

2023-04-16 0 510

您好,我是bp技术知识库,欢迎关注。


插槽在Vue中是一个十分常见以及经常会使用到的功能,它的存在大大提高了组件的复用性,很多时候我们都需要使用插槽来将组件进行复用。

在平时的插槽使用中,我们大部分时间都仅仅使用了插槽的一些简单功能,但其实插槽还有更多高级的功能,比如说能将子组件中的数据传递到父组件中,父组件中能够访问到该传递的数据。

因为一些原因,官方已经废弃了之前插槽的用法,相信只要使用Vue框架的人肯定都用过Element UI,但其实Element UI的表格插槽使用方式其实现在已经过时了,就如下面代码。

<template slot-scope="scope">
    <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
    <el-button type="text" size="small">编辑</el-button>
</template>

官方声明在Vue3.x版本时,已经不再对这种插槽使用方式进行支持。

1. 写法

插槽的使用是非常简单的,这里要分两种情况:

  • 默认插槽:即<slot />这种不带name属性的为默认插槽,但是在某些情况下,我们需要在不同的地方插入不同的值,所以就需要使用到具名插槽。
  • 具名插槽:即<slot name="header" />这种带有name属性的插槽。

其实<slot />这种默认插槽是附带了name属性的,只是它的name属性为default,在一般情况下我们会将它进行省略。

下面我们分别来看一下默认插槽和具名插槽。

<template>
  <div>
    <header>
      <!-- 这里是具名插槽 -->
      <slot name="header" />
    </header>
    <!-- 这是默认插槽 -->
    <!-- 下面这两种插槽本质都是默认插槽 -->
    <slot />
    <slot name="default" />
  </div>
</template>

<script>
export default {
  name: "SlotTest"
};
</script>

<style>
header {
  font-size: 30px;
  font-weight: bold;
}
</style>

上面这段代码分别声明了默认插槽和具名插槽,其中同名的插槽是可以多次声明的,并不是只能声明一次。

当声明多次的时候,插入的内容也会变成两份。例如我们使用以下默认插槽:

<slot-test>
  Hello default slot!
</slot-test>

这个时候运行项目,会发现在浏览器中会出现两个Hello default slot!

那么大概知道了这些内容后,我们就来看一下具名插槽和默认插槽分别是怎么用的。

推荐写法

官方在2.6.0版本中,修改了插槽的用法,现在推荐使用<template v-slot:header>这种写法来调用具名插槽。

<slot-test>
  <!-- 具名插槽的用法 -->
  <template v-slot:header>
    Hello header slot!
  </template>
  <!-- 这是一种默认插槽的用法 -->
  <template v-slot:default>
    Hello header slot!
  </template>
  <!-- 这是另一种默认插槽的用法 -->
  Hello header slot!
</slot-test>

需要注意的是,v-slot属性只有当标签为<template />才会生效,如果是其它标签是无法调用插槽的,例如:

<div v-slot:header>
    Hello header slot!
</div>

不仅不能调用,甚至还会报错。

值得注意的是,v-slotv-onv-bind一样,也有缩写,那就是#,所以上面的代码也可以写成下面这样:

<slot-test>
  <!-- 具名插槽的用法 -->
  <template #header>
    Hello header slot!
  </template>
  <!-- 这是一种默认插槽的用法 -->
  <template #default>
    Hello header slot!
  </template>
  <!-- 这是另一种默认插槽的用法 -->
  Hello header slot!
</slot-test>

过时写法

由于官方文档的排版问题,我在最开始读文档的时候搞不清哪个是过时用法,反复读了几遍后,终于发现<div slot="header"></div>这种语法使用插槽就为过时语法,官方在文档说在Vue3中不会再兼容这种写法:

<slot-test>
  <div slot="header">
    Hello header slot!
  </div>
</slot-test>

与上面的推荐写法不同,slot不仅仅可以声明在<template />标签上,还可以声明在其它的HTML标签上面,比如上面的div标签。

2. 向父组件传值

有时候我们需要将子组件中的属性值传递到父组件,让父组件在使用插槽的时候能够取得这些值,例如下面的代码:

<template>
  <div>
    <header>
      <!-- 这里是具名插槽 -->
      <slot name="header" />
    </header>
    <!-- 这是默认插槽 -->
    <!-- 下面这两个插槽本质是同一个 -->
    <slot />
    <slot name="default" />
  </div>
</template>

<script>
export default {
  name: "SlotTest",
  data() {
    return {
      // 该值希望在父组件中可以获取并且调用
      describe: "插槽的使用"
    };
  }
};
</script>

<style>
header {
  font-size: 30px;
  font-weight: bold;
}
</style>

可以看到,我们希望在父组件中获取到子组件的describe值,那么这种情况怎么进行处理呢?

<slot-test>
  {{ describe }}
  Hello header slot!
</slot-test>

像上面这种方式直接尝试调用describe属性显然是不现实的,会直接进行报错,那么我们就来看一下究竟如何在父组件中获得describe属性值吧。

2.1 推荐写法

官方在2.6.0版本中同样修改了这一部分的写法。

首先我们要想在父组件中获得该属性,就必须在插槽上面进行传递:

<div>
  <header>
    <slot name="header" :describe="describe" />
  </header>
  <slot :describe="describe" />
</div>

这个时候在父组件中就可以获取到传递出来的describe值:

<slot-test v-slot="slotProps">
  {{ slotProps.describe }}
</slot-test>

注意:子组件中传出来的是一个对象,即:{ "describe": "插槽的使用" }。并不是describe的值,所以slotProps这个变量其实取什么名字都是可以的。

具名插槽也是同样:

<slot-test>
  <template #header="slotProps">
    {{ slotProps.describe }}
  </template>
  <!-- 一旦有具名插槽,默认插槽就必须这样写 -->
  <template v-slot:default="slotProps">
    {{ slotProps.describe }}
  </template>
</slot-test>

需要值得注意的是,一旦有了具名插槽,默认插槽就不能再像上面一样,直接声明到slot-test上,这会导致作用域不明确而报错。

2.1.1 解构插槽Prop

插槽Prop是可以直接通过ES6语法来解构的:

<slot-test>
  <template #header="{ describe }">
    {{ describe }}
  </template>
  <!-- 一旦有具名插槽,默认插槽就必须这样写 -->
  <template v-slot:default="{ describe }">
    {{ describe }}
  </template>
</slot-test>

2.2 过时写法

过时写法看一下就好了,虽然Element UI的表格那块插槽示例依然还是这种写法,但是Vue官方已经不推荐了。

<slot-test>
  <template slot="header" slot-scope="slotProps">
    {{ slotProps.describe }}
  </template>
  <!-- 这是过时写法 -->
  <template slot-scope="slotProps">
    {{ slotProps.describe }}
  </template>
</slot-test>

3. 最后

插槽的用法是非常灵活的,知道了上面的那些基础知识后,你也可以制作出一些十分方便的组件。

同时非常推荐去读一下官方文档中的插槽介绍,你可能会发现一些新大陆。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务