12. 插槽

2022-10-12 16:08:13发布
88

默认插槽

父组件

<template>
  <div id="app">
    <MyBanner>
        <div>头部</div>
    </MyBanner>
  </div>
</template>

子组件

<template>
    <div>
        <slot>header</slot>
    </div>
</template>

父组件的<div>头部</div> 将会替换子组件的<slot>header</slot>

tips:子组件的<slot>header</slot>,如果父组件没有传递数据过来,则默认显示<slot>header</slot>。比如这样:

<template>
  <div id="app">
    <MyBanner>
      <!--这里什么都没有-->
    </MyBanner>
  </div>
</template>

<slot>header</slot>将会被替换成<div>header</div>


具名插槽

父组件

<template>
  <div id="app">
    <MyBanner>
      <div slot="footer">底部</div>
    </MyBanner>
  </div>
</template>

子组件

<template>
    <div>
        <slot name="footer"></slot>
    </div>
</template>

父组件的<div slot="footer">底部</div>将会替换子组件的<slot name="footer"></slot>

在日常的开发中,有时候我们需要传递的数据不是dom元素,而是一个template标签。传递template标签有以下2种传递方式 :

传递方式1(父组件)

<template>
  <div id="app">
    <MyBanner>
      <template slot="footer"> <!--还是用slot起名字-->
        <div>底部</div>
      </template>
    </MyBanner>
  </div>
</template>

传递方式2 (父组件)

<template>
  <div id="app">
    <MyBanner>
      <template v-slot:footer><!--用v-slot起名字-->
        <div>底部</div>
      </template>
    </MyBanner>
  </div>
</template>

子组件

<template>
    <div>
        <slot name="footer"></slot>
    </div>
</template>

大部分情况下,你应该用第二种方式。需要注意的是,v-slot:footer是可以简写的,如:

<template>
  <div id="app">
    <MyBanner>
      <template #footer> <!--把v-slot:改成#-->
        <div>底部</div>
      </template>
    </MyBanner>
  </div>
</template>


作用域插槽

此插槽用于子组件向父组件传递数据,刚好和上面介绍的插槽相反。

例子

子组件

<template>
    <div>
        <slot :navList="navList"></slot>
    </div>
</template>
<script>
export default {
    data() {
        return {
            navList: [{
                name: 'baidu',
                url: 'https://www.baidu.com'
            },{
                name: 'google',
                url: 'https://www.google.com'
            }]  
        }
    }
}
</script>

父组件

<template>
  <div id="app">
    <MyBanner>
      <template v-slot="myBannerProps"> <!--v-slot除了可以用来起名字外,还可以用来接收子组件传递过来的数据。需要注意的是接收数据是等号,起名字是冒号-->
        <ul>
          <li v-for="(item, key) in myBannerProps.navList" :key="key">
            {{ item.name }} --- {{ item.url }}
          </li>
        </ul>
      </template>
    </MyBanner>
  </div>
</template>

<script>
import MyBanner from './components/MyBanner.vue'
export default {
  components: {
    MyBanner
  }
}
</script>

tips:如果子组件的插槽是具名插槽,则父组件可以这样写 :

子组件

<template>
    <div>
        <slot name="content" :navList="navList"></slot> <!--具名插槽-->
    </div>
</template>
<script>
export default {
    data() {
        return {
            navList: [{
                name: 'baidu',
                url: 'https://www.baidu.com'
            },{
                name: 'google',
                url: 'https://www.google.com'
            }]  
        }
    }
}
</script>

父组件

<template>
  <div id="app">
    <MyBanner>
      <template #content="myBannerProps"> <!--#content代表替换子组件name为content的插槽,="myBannerProps" 代表接收子组件发送过来的数据-->
        <ul>
          <li v-for="(item, key) in myBannerProps.navList" :key="key">
            {{ item.name }} --- {{ item.url }}
          </li>
        </ul>
      </template>
    </MyBanner>
  </div>
</template>

<script>
import MyBanner from './components/MyBanner.vue'
export default {
  components: {
    MyBanner
  }
}
</script>