你所不知道的Vue插槽

952 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

好吧,我是标题党,其实是vue插槽的基础使用(手动狗头)

什么是插槽

vue官网上是这样定义的
    Vue 实现了一套内容分发的 API,将 `<slot>` 元素作为承载分发内容的出口。

我的理解是父组件可以在子组件中选择性的插入标签,文本,组件,从而实现组件的复用

插槽的使用

默认插槽 default

默认插槽不需要给定name属性,可以直接使用,我们先创建一个子组件SlotCpn,给他一个插槽solt

defult子组件.png

在父组件中引用,并且使用插槽

defult父组件.png

此时我们运行程序,可以看到,1这个内容已经被插入到slot里面去了

defult浏览器.png

如果我们不在子组件中定义solt,这个1是不会显示在浏览器中的,感兴趣的小伙伴可以去试试

这个时候可能就会有人问,如果我有多个插槽那么这个1会插入到那个里面呢,直接告诉大家,它会被插入到每一个插槽里面,给大家看一下

我们在子组件中定义4个插槽 子多个插槽.png

此时每一个插槽都会被插入一个 浏览器多插槽.png

如果想要只有第一个插槽插入1,其他的不插入,要怎么办呢? 这个时候就引入了我们的具名插槽

具名插槽

顾名思义,具名插槽就是有name的插槽

我给子组件中第一个的slot标签添加name属性

子组件
<template>
    <div>
        <div>开始</div>
        <slot name="scc"></slot>
        <slot></slot>
        <slot></slot>
        <slot></slot>
        <div>结束</div>
    </div>
</template>

来到父组件,在父组件添加template标签,添加v-slot:name属性,并且把在插槽里面插入的值放进template里面

父组件
<template>
  <div>
      <slot-cpn>
            <template v-slot:scc>
                <div>1</div>
            </template>
      </slot-cpn>
  </div>
</template>

浏览器具名插槽.png

此时浏览器只显示了一个插槽内容

其实刚才的默认插槽也是有name的,他的name是default,我们可以测试一下,添加一个新的templat,让他的v-slot:defaul,来证明我们说的对不对

父组件添加default
<template>
  <div>
      <slot-cpn>
            <template v-slot:scc>
                <div>1</div>
            </template>
            <template v-slot:default>
                <div>default</div>
            </template>
      </slot-cpn>
  </div>
</template>

此时我们看一下浏览器展示效果

默认插槽的name.png

可以看到,其他没有命名的slot已经被渲染成default

证明我们说的是没问题的

动态插槽

动态插槽可以让我们动态的给插槽内容,用来展示不同的内容,封装高级组件的基础

首先我们定义一个数据name,并且通过props传给子组件,子组件接收,使用name作为插槽的name,父组件v-slot:[name],这样一个简易的动态插槽就完成了

子组件
<template>
    <div>
        <div>开始</div>
        <slot :name="name"></slot>  //插槽name
        <div>结束</div>
    </div>
</template>
<script>
export default {
    props:['name']
}
</script>
父组件
<template>
  <div>
      <slot-cpn :name="name">   //传给子组件name
            <template v-slot:[name]>    //插槽name
                <div>{{name}}</div>
            </template>
      </slot-cpn>
  </div>
</template>
<script>
export default {
    components:{
        SlotCpn
    },
    data() {
        return {
            name:'scc'
        }
    },
}
</script>

这样简易的动态插槽完成了

作用域插槽

对于组件渲染是有作用于的,如果父子之间的值不传递,是没法子数据在父组件中拿到的
作用域插槽可以解决我们的这个问题

写一个经典的案例

我们想封装一个组件,用来展示父组件传来的一些数据,先定义数据

父组件
data() {
    return {
        list:["衣服",'裤子',"鞋子"]
    }
},

把list传给子组件,并且让子组件渲染

图解传值.png

我们可以通过v-slot="SlotProps"拿到传来的item。并且展示,个人认为也是一种组件中的传值方式,不过只能用在slot

看一下此时的浏览器

图解.png 列表已经渲染出来了

那么这样的slot如何命名呢,很简单

v-slot:scc="SlotProps" 这样就可以了

独占默认插槽

当我们的插槽只有默认插槽时,我们就可以直接使用独占默认插槽(删掉template标签,直接写在组件标签上)
也就是一种简写方式,如果有个插槽有name,那么就会报错
<template>
  <div>
      <slot-cpn :list="list"  v-slot='SlotProps'>
            <button>{{SlotProps.item}}</button>
      </slot-cpn>
  </div>
</template>

此时浏览器依旧可以渲染出来,但是一旦添加了具名插槽就会报错,大家要注意

结束

今天分享到此为止,希望大家快了!!!加油!