iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0
Vue.js

Vue.js 新手入門之路系列 第 25

Vue.js 新手入門之路 - slot (三)

  • 分享至 

  • xImage
  •  

作用域 slot

slot 是無法直接子元件的內容的,若我們同時需要使用父元件、子元件的 data 便可以使用 props 的做法,對 slot 的出口做傳遞
eg.
子元件先透過 slot 屬性把 data 傳出去

<script setup>
const Message = 'hello from son'
</script>

<template>
  <div class="box">
    <slot :text="Message" :count="1"></slot>
  </div>
</template>


<style scoped>
.card { 
    border:1px solid #ddd;
    border-radius:8px;
    padding:12px; 
}
.header { 
    font-weight:700;
    margin-bottom:8px; 
}
.footer { 
    margin-top:8px;
    color:#666; 
}
</style>

父元件接收到一個 slotProps 物件,再操作

<script setup>
import { ref } from 'vue'
import scopedslot from './components/slot.vue'
const attr = ref('box')
</script>

<template>
  <scopedslot v-slot="slotProps">
    {{ slotProps.text }} - {{ slotProps.count }}
  </scopedslot>
</template>

<style scoped>
  .box{
    display: flex;
    gap:3px;
    text-align: center;
    justify-content: center;
    flex-direction: column;
    font-size: x-large;
    margin-left: 450px;
    margin-top: 5px;
    padding: 35px;
  }
</style>

直接使用解構的寫法同樣可以取得

  <scopedslot v-slot="{ text, count }">
    {{ text}} - {{ count }}
  </scopedslot>

https://ithelp.ithome.com.tw/upload/images/20250913/20178296BOM6p79Ndr.png

具名的作用域 slot

name 是保留字不會被傳出,真正傳出去的是 message

<script setup>
const headerMsg = 'son header '
const footerMsg = 'son footer'
</script>

<template>
  <header>
    <slot name="header" message="hello" :info="headerMsg"></slot>
  </header>

  <main>
    <slot :payload="{ ok: true }"></slot>
  </main>

  <footer>
    <slot name="footer" :note="footerMsg"></slot>
  </footer>
</template>

這是一個同時有「具名插槽」與「預設插槽」時,預設插槽就得用 <template #default> 才能正確取得它的 slot props,否則會有 compile error 或作用域的混淆。

<script setup>
import { ref } from 'vue'
import scopedslot from './components/slot.vue'
const attr = ref('box')  
</script>

<template>
  <div :class="attr">
    <scopedslot>
      <template #default="{ payload }">
        default: {{ payload.ok }}
      </template>

      <template #header="{ message, info }">
        header: {{ message }} / {{ info }}
      </template>

      <template #footer="{ note }">
        footer: {{ note }}
      </template>
    </scopedslot>
  </div>
</template>

<style scoped>
  .box{
    display: flex;
    gap:3px;
    text-align: center;
    justify-content: center;
    flex-direction: column;
    font-size: x-large;
    margin-left: 450px;
    margin-top: 5px;
    padding: 35px;
  }
</style>

https://ithelp.ithome.com.tw/upload/images/20250913/20178296Di5FBYo9oq.png

ref:
https://vuejs.org/guide/components/slots.html


上一篇
Vue.js 新手入門之路 - slot (二)
系列文
Vue.js 新手入門之路25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言