DEV Community

Cover image for pass custom content จาก parent -> child ด้วย slot
thinny
thinny

Posted on

pass custom content จาก parent -> child ด้วย slot

ปกติแล้วเวลาเราจะส่งค่า จาก parent component ไปหา child component จะต้องส่งด้วย props แต่ปัญหาอย่างหนึ่งในการ ส่งค่าข้าม component คือ ถ้าข้อมูลมาขนาดใหญ่ และข้อมูลอยู่ในรูปแบบ html จะเริ่มทำยากแล้วครับ ถ้าเราเจอ case study แบบนี้เราจะมี solution มาแก้ปัญหายังไง มาดูกันครับ

slot คืออะไร

slot หรือ slot tag หรือ slot element มันคือ html element อันนึงใน webcomponent ที่ช่วยให้เราสามารถรับค่าจาก parent component ได้ หรือหากเราต้องการเจาะช่องไว้ เพื่อให้ content บางอย่างมาแสดงเฉพาะส่วนที่เราเจาะช่องไว้ก็ได้

มาเตรียม component กันก่อน

<!-- App.svelte -->
<script>
    import Box from './Box.svelte';
</script>

<!-- ใช้งาน Box -->
<Box>

</Box>
Enter fullscreen mode Exit fullscreen mode
<!-- Box.svelte -->
<style>
    .box {
        width: 300px;
        border: 1px solid #aaa;
        border-radius: 2px;
        box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
        padding: 1em;
        margin: 0 0 1em 0;
    }
</style>

<div class="box">

</div>
Enter fullscreen mode Exit fullscreen mode

ถ้าเราต้องการส่งค่าจาก parent -> child ผ่าน prop

<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
   const title = 'Title Prop'

</script>

<!-- ใช้งาน Box -->
<Box {title} />
Enter fullscreen mode Exit fullscreen mode
<!-- Box.svelte -->
<script>
export let title;
</script>

<div class="box">
  {title}
</div>
Enter fullscreen mode Exit fullscreen mode

ส่งค่า ผ่าน prop โดยข้อมูลเป็น html

<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
   const title = '<h1>Title Prop</h1>'
</script>

<!-- ใช้งาน Box -->
<Box {title} />
Enter fullscreen mode Exit fullscreen mode
<!-- Box.svelte -->
<script>
export let title;
</script>

<div class="box">
  {@html title}
</div>
Enter fullscreen mode Exit fullscreen mode

ในกรณีอาจจะยังไม่เห็นว่ามันมีปัญหายังไง คราวนี้เราลองใส่ข้อมูลไปใน ตัวแปร title เยอะขึ้น ผสมกับ html tag ไปด้วย จะเห็นว่ามันจัดระเบียบข้อมูลยากขึ้น ถ้ายังไม่เห็นภาพ เพิ่ม style เข้าไปอีก ข้อมูลเริ่มรกละ

ถ้าเกิดว่าเราจัดโครงสร้างข้อมูลเอง ทำ block content อาจจะมี style ร่วมด้วย แต่ว่าดูสะอาดตามากขึ้น เราสามารถแก้ปัญหานี้ slot tag ครับ มาดูกัน

<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
</script>

<!-- ใช้งาน Box -->
<Box>
  <h1>Slot Title</h1>
</Box>
Enter fullscreen mode Exit fullscreen mode
<!-- Box.svelte -->
<div class="box">
  <slot />
</div>
Enter fullscreen mode Exit fullscreen mode

ลองมาวางโครงและใส่ข้อมูลเยอะมากขึ้น

<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
</script>

<!-- ใช้งาน Box -->
<Box>
  <div class="title">
    <h1>Slot Title</h1>
  </div>

  <div class="sub_title">
    <h4>Slot SubTitle</h4>
  </div>

  <div class="content">
    <p>content...</p>
  </div>

</Box>
Enter fullscreen mode Exit fullscreen mode
<!-- Box.svelte -->
<div class="box">
  <slot />
</div>
Enter fullscreen mode Exit fullscreen mode

จากตัวอย่างจะเห็นว่าไม่ว่าเราจะใส่ content มากแค่ไหน มันก็ยังดูสะอาดตา เพราะมันเป็นโครงสร้าง html ทั่วไปที่เราคุ้นเคยอยู่แล้ว แถมยังสามารถจัดโครงสร้าง content ได้เองอีกด้วย <slot /> ถ้าเรากำหนดแบบนี้ ที่ฝั่ง component ลูก เราจะเรียกว่า default slot ไม่ว่าเราจะใส่ content มาในรูปแบบไหน มันจะมาลงที่ defualt slot นี้เลย นี่ก็เป็นแค่ตัวอย่างการใช้ slot tag ง่ายๆนะครับ

Alt Text

ศึกษาเพิ่มเติมเรื่อง slot tag ได้ที่ slot tag

หากสนใจ svelte สามารถเรียนรู้การใช้งาน svelte แบบ step by step ได้ที่
Svelte: Framework Not Framework — (ตอนที่ 1) แรกรู้จัก

ขอบคุณทุกท่านที่อ่านมาถึงตรงนี้ ถ้าอ่านแล้วรู้มีประโยชน์ ฝากกด Subscribe หรือ share link ให้คนอื่นรับรู้ด้วยนะครับ ขอบคุณครับ

Discussion (0)