vue组件插槽

组件插槽

如下代码所示:

Vue.component('fun-div', {
  template: `
    <div>
      <strong>before</strong>
      <slot></slot>
      <strong>after</strong>
    </div>
  `
})

上面组件的模板中,使用 <slot> 标签声明了一个插槽,当使用 <fun-div> 标签时,自动将标签中的内容添加到 <slot> 的位置。如下 HTML 代码:

<div class="container">
  <fun-div>
    这是中间的内容
  </fun-div>
</div>

结果:
在这里插入图片描述

实际上,在 <fun-div> 标签中可以插入任何内容,也可以是其他组件、模板内容。比如插入一个 input 标签:

<div class="container">
  <fun-div>
    <input type="text">
    这是中间的内容
  </fun-div>
</div>

结果:
在这里插入图片描述

还可以为插槽定义默认内容,当没有内容填充插槽时,将显示默认内容,如下代码所示:

Vue.component('fun-div', {
  template: `
    <div>
      <strong>before</strong>
      <slot>这是默认内容</slot>
      <strong>after</strong>
    </div>
  `
})
<div class="container">
  <fun-div>这是中间的内容</fun-div>
  <fun-div></fun-div>
</div>

结果:
在这里插入图片描述

具名插槽

在插槽 <slot> 标签中设置 name 属性可以分辨 <slot> 标签,也就是可以设置多个插槽,如下代码所示:

Vue.component('fun-div', {
  // 具名插槽的用法就是使用 name 属性标识出 slot 标签的名称,
  // 在使用标签插入内容时可以使用 slot 属性的属性值来分辨插槽
  template: `
    <div>
      <slot name="header"></slot>
      <slot></slot>
      <slot name="footer"></slot>
    </div>`
})

上面代码中第 6 行使用 name<slot> 进行区分,在插入内容时,可以使用 slot 属性为具体的 <slot> 插槽插入内容。如下代码所示:

<div class="container">
  <fun-div>
    <p slot="header">这是 header 插槽中的内容</p>
    <p slot="footer">这是 footer 插槽中的内容</p>
    <p>普通插槽</p>
  </fun-div>
</div>

上面代码中第 3 行,设置 slot="header" 在 JS 部分的 name="header" 插槽中插入内容。

结果:
在这里插入图片描述

通常在 HTML 中使用 <template> 标签在一个具名插槽中插入多个 html 标签,而 <template> 标签不在 HTML 结构中显示,如下代码所示:

<fun-div>
  <template slot="header">
    <div>这是 header 标签中插入的第一个 div</div>
    <input type="text" value="header">
  </template>
  <template slot="footer">
    <div>这是 header 标签中插入的第一个 div</div>
    <input type="text" value="footer">
  </template>
  <p>普通插槽</p>
</fun-div>

结果:
在这里插入图片描述

作用域插槽

可以在子组件中使用 v-bind 指令设置属性,属性值为要传递的数据。在父组件中使用 <template slot-scope="slotProps"> </template> 将子组件传递的数据保存到 slotProps 对象中。

需要注意的是,slotProps 为一个对象,获取的子组件也是一个对象,如下面 HTML 代码第 8-10 行注释所示。

如下代码所示:

Vue:

Vue.component('fun-div', {
  // 接受父组件传来的值
  props: ['list'],
  // 下面模板中使用 <slot v-bind:msg='item'> 绑定了 msg 属性,将值传递到父组件中
  template: `
  <div>
    <ul>
      <li v-for="(item, index) in list" :key="item.id">
        <slot v-bind:msg='item'>
          {{item.name}} 
        </slot>
      </li>
    </ul>
  </div>
  `
})
    
let vm = new Vue({
  el: '.container',
  data: {
    list: [
    {id: 1, name: "apple"}, 
    {id: 2, name: "banana"},
    {id: 3, name: "orange"}]
  }
})

HTML:

<div class="container">
  <!-- 设置 list属性向子组件传值 -->
  <fun-div :list='list'>
    <!-- 通过 slot-scope 属性获得子组件中传递来的 数据
      将数据存到了 slotProps 对象中
    -->
    <template slot-scope="slotProps">
      <!-- 通过 slotProps 对象的 msg.name 访问每个数据的名称
        因为 <slot v-bind:msg='item'> 绑定的是 msg 属性,所以需要.msg
      -->
      <strong v-if="slotProps.msg.id == 2">{{ slotProps.msg.name }}</strong>
      <span v-else>{{ slotProps.msg.name }}</span>
    </template>
  </fun-div>
</div>

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值