Dev to webs {Coding…}

เรียนรู้การพัฒนาซอฟเวอร์ เพื่อความรู้ที่ยั่งยืน

บทที่ 35: การรวม Component ซ้อนกัน


1. ความเข้าใจเกี่ยวกับ Component ซ้อนกัน

ใน Alpine.js Component ซ้อนกัน หมายถึงการสร้าง Component ภายใน Component เพื่อแยกส่วนการทำงานหรือจัดกลุ่ม State และฟังก์ชันให้เป็นระเบียบ

  • ใช้ x-data สำหรับจัดการ State ภายใน Component แต่ละตัว
  • Component ภายในสามารถส่งข้อมูลหรือสื่อสารกับ Component ภายนอกผ่าน Event หรือ Store

2. การใช้งาน Component ซ้อนกัน

ตัวอย่าง 1: Component ภายใน Component
<div x-data="{ parentMessage: 'Hello from Parent!' }">
    <p x-text="parentMessage"></p>
    <div x-data="{ childMessage: 'Hello from Child!' }">
        <p x-text="childMessage"></p>
    </div>
</div>

คำอธิบาย:

  • Component ภายนอกมี State parentMessage
  • Component ภายในมี State แยกกัน (childMessage) โดยไม่เกี่ยวข้องกับ Component ภายนอก

3. การสื่อสารระหว่าง Component ซ้อนกัน

ตัวอย่าง 2: ส่งข้อมูลจาก Parent ไปยัง Child ผ่าน Props
<div x-data="{ message: 'Hello from Parent!' }">
    <p>Parent Message: <span x-text="message"></span></p>
    <div x-data="{ parentMessage: $el.parentNode.__x.$data.message }">
        <p>Child Received: <span x-text="parentMessage"></span></p>
    </div>
</div>

คำอธิบาย:

  • ใช้ $el.parentNode.__x.$data เพื่อเข้าถึง State ของ Component Parent
  • Child Component รับข้อความจาก Parent และแสดงใน <span>

4. การใช้ Event สื่อสารจาก Child ไปยัง Parent

ตัวอย่าง 3: ส่งข้อมูลจาก Child ไปยัง Parent
<div x-data="{ message: '', updateMessage(newMessage) { this.message = newMessage; } }">
    <p>Parent Message: <span x-text="message"></span></p>
    <div x-data>
        <button @click="$dispatch('update-message', { newMessage: 'Hello from Child!' })">
            Send to Parent
        </button>
    </div>
    <div @update-message.window="updateMessage($event.detail.newMessage)"></div>
</div>

คำอธิบาย:

  • Child Component ส่ง Event update-message พร้อมข้อมูล newMessage
  • Parent Component รับ Event และอัปเดต State message

5. การจัดการ State ร่วมกันใน Component ซ้อนกัน

ตัวอย่าง 4: ใช้ Alpine.store เพื่อแชร์ State
<script>
    document.addEventListener('alpine:init', () => {
        Alpine.store('sharedState', {
            counter: 0,
            increment() {
                this.counter++;
            },
            decrement() {
                this.counter--;
            }
        });
    });
</script>

<div x-data>
    <h2>Parent Component</h2>
    <p>Counter: <span x-text="$store.sharedState.counter"></span></p>
    <button @click="$store.sharedState.increment()">Increment</button>
    <button @click="$store.sharedState.decrement()">Decrement</button>
    <div x-data>
        <h3>Child Component</h3>
        <p>Counter (Shared): <span x-text="$store.sharedState.counter"></span></p>
    </div>
</div>

คำอธิบาย:

  • ใช้ Alpine.store ชื่อ sharedState เพื่อเก็บ State ที่แชร์ระหว่าง Parent และ Child
  • Parent และ Child Component สามารถอ่านและเปลี่ยนค่าของ counter ได้พร้อมกัน

6. การซ้อน Component พร้อม Transition

ตัวอย่าง 5: ใช้ Transition ใน Component ซ้อนกัน
<div x-data="{ isVisible: false }">
    <button @click="isVisible = !isVisible">Toggle Child</button>
    <div x-show="isVisible" x-transition>
        <div x-data="{ childMessage: 'Hello from Child!' }">
            <p x-text="childMessage"></p>
        </div>
    </div>
</div>

คำอธิบาย:

  • Parent Component ควบคุมการแสดง/ซ่อนของ Child Component ผ่าน x-show
  • Child Component มี State แยกจาก Parent

7. การซ้อน Component หลายระดับ

ตัวอย่าง 6: Component ซ้อนกันหลายชั้น
<div x-data="{ parentMessage: 'Hello from Parent!' }">
    <p x-text="parentMessage"></p>
    <div x-data="{ childMessage: 'Hello from Child!' }">
        <p x-text="childMessage"></p>
        <div x-data="{ grandchildMessage: 'Hello from Grandchild!' }">
            <p x-text="grandchildMessage"></p>
        </div>
    </div>
</div>

คำอธิบาย:

  • Parent Component มี State parentMessage
  • Child Component และ Grandchild Component มี State แยกจากกัน

8. ข้อควรระวังในการใช้ Component ซ้อนกัน

  1. การจัดการ State:
    • หาก Component ซ้อนกันลึกเกินไป ควรพิจารณาใช้ Alpine.store เพื่อจัดการ State ร่วมกัน
  2. การสื่อสารระหว่าง Component:
    • ใช้ Event หรือ Props สำหรับการสื่อสารที่จำเป็นเท่านั้น
  3. โครงสร้าง DOM:
    • ออกแบบโครงสร้าง DOM ให้เรียบง่ายเพื่อป้องกันปัญหาซับซ้อนในการจัดการ

สรุป

ในบทนี้ คุณได้เรียนรู้การใช้งาน Component ซ้อนกัน ใน Alpine.js ตัวอย่างครอบคลุมการจัดการ State ภายใน Component, การส่งข้อมูลระหว่าง Parent และ Child Component, การใช้ Event, และการแชร์ State ด้วย Alpine.store การรวม Component ซ้อนกันช่วยให้โค้ดมีโครงสร้างที่ชัดเจนและง่ายต่อการจัดการในโปรเจกต์ที่ซับซ้อน!