Vue3父子组件插槽的使用方式

1,554 阅读2分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

什么是插槽

插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。

插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

基本使用

编写一个父组件

<body>
    <div id="app"></div>
</body>

<script>
    const app = Vue.createApp({
        template: ` <h2>父组件</h2>`
    })

    const vm = app.mount("#app")
</script>

再写一个子组件

app.component('son', {
    template: `
        <div>
            <h3>子组件</h3>
        </div>
    `
})

父组件调用子组件

const app = Vue.createApp({
        template: ` <h2>父组件</h2><son />`
    })

插槽如何使用呢?

只需要在子组件中加入<slot></slot>,然后在父组件中使用。

app.component('son', {
    template: `
        <div>
            <h3>子组件</h3>
            <slot></slot>
        </div>
    `
})
const app = Vue.createApp({
        template: ` <h2>父组件</h2><son>这是父组件要在子组件中显示的内容</son>`
    })

运行效果:

image.png

插槽支持任何DOM元素,比如我们添加style样式

const app = Vue.createApp({
    template: `
        <h2>父组件</h2>
        <son>
            <div style="color:red;font-size:25px">这是父组件要在子组件中显示的内容</div>
        </son>
      `
 })

默认插槽

定义默认插槽通过slot组件定义,定义好了之后,就相当于一个坑,你可以把它理解为电脑上usb插口。

我们可以将默认文本放在<slot>标签内:

app.component('son', {
    template: `
        <div>
            <h3>子组件</h3>
            <slot>子组件的默认内容</slot>
        </div>
    `
})

现在使用父组件去调用:

const app = Vue.createApp({
template: ` <h2>父组件</h2><son/>`
    })

运行效果:

image.png

具名插槽

有时会需要多个插槽,<slot>元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽 例如:

app.component('son', {
    template: `
        <div>
            <h3>公民基本信息</h3>
            <slot>
                <!--姓名-->
            </slot>
            <slot>
                <!--年龄-->
            </slot>
            <slot>
               <!--性别-->
            </slot>
        </div>
    `
})

像这种情况,<slot>有一个特殊的属性name

app.component('son', {
    template: `
        <div>
            <h3>公民基本信息</h3>
            <slot name="name">
                姓名
            </slot>
            <slot name="age">
                年龄
            </slot>
            <slot name="sex">
               性别
            </slot>
        </div>
    `
})

如何使用呢?很简单只需要在DOM元素上,使用v-slot注明使用的插槽名称:

const app = Vue.createApp({
template: `
    <h2>父组件</h2>
    <son>
        <template v-slot:name>小明</template>
        <template v-slot:age>7</template>
        <template v-slot:sex>男</template>
    <son/>
`
    })

运行效果:

image.png

v-slot:name这种语法可以简写成#name,代码如下:

const app = Vue.createApp({
template: `
    <h2>父组件</h2>
    <son>
        <template #name>小明</template>
        <template #age>7</template>
        <template #sex>男</template>
    <son/>
`
    })

注:只要出现多个插槽,所有的插槽使用完整的基于?<template>?的语法。

插槽的作用域

有时让插槽内容能够访问子组件中才有的数据是很有用的。

写一个子组件:

const app = Vue.createApp({
data(){
    return {
       list:['A','B','C']
    }
},
template: `<div v-for="item in list">{{item}}</div>`
})

父组件想使用子组件插槽中的值,可以使用:绑定的形式进行传递,比如写成:item="item",具体的代码可以写成下面的样子。

const app = Vue.createApp({
data(){
    return {
                list:['A','B','C']
            }
},
template: `
        <div>
            <slot v-for="item in list" :item="item" />    
        </div>`
})

写完后父组件中用v-slot="xxx"的形式接受,接收后就可以使用了

const app = Vue.createApp({
    template: `  
    <list v-slot="props"> 
        <span>{{props.item}}</span> 
    </list>
`

注意这里的props是子组件传递过来的数据都是对象,但你也可以使用任意你喜欢的名字。