Aesthetic study notes about Vue.js v-for and v-if directives on an iPad screen

1. 🎯 ตอนที่ 13: พลังของ v-for และ v-if สยบข้อมูลนับพันด้วยเงื่อนไขดั่งใจนึก

2. 📖 เปิดฉาก (The Hook)

น้องๆ ลองจินตนาการว่าเรากำลังทำระบบ E-commerce ที่มีสินค้าเป็นพันๆ ชิ้นดูสิครับ เราได้รับโจทย์ว่า “ให้ดึงสินค้าทั้งหมดมาแสดงผล แต่ถ้าสินค้าชิ้นไหนหมดสต๊อก ให้ซ่อนเอาไว้ และถ้าผู้ใช้ยังไม่ล็อกอิน ให้ขึ้นข้อความเตือน”

ถ้าเป็นยุคสมัยที่ต้องเขียน Vanilla JavaScript เราคงต้องเขียนลูป for สร้าง Element ยัดลงไปทีละบรรทัด พร้อมกับเขียนเงื่อนไข if ตรวจจับสถานะกันวุ่นวายจนโค้ดพันกันเป็นสปาเกตตีแน่นอน แต่ในอาณาจักร Vue.js เรามี “เวทมนตร์วิเศษ” ที่ชื่อว่า List Rendering (v-for) และ Conditional Rendering (v-if) ที่จะมาช่วยเสกให้ UI ของเราตอบสนองตามข้อมูลได้อย่างงดงาม

วันนี้พี่จะพาจิบกาแฟ และเจาะลึกวิธีการใช้งาน 2 คำสั่ง (Directives) นี้ พร้อมเปิดเผย “กฎเหล็กคลาสสิก” ที่นักพัฒนา Vue มือใหม่มักตกหลุมพรางจนแอปพังกระจาย มาดูกันครับว่ามือโปรเขาเขียนกันอย่างไร!

3. 🧠 แก่นวิชา (Core Concepts)

ก่อนอื่นเรามาแยกหน้าที่ของสองขุนพลนี้กันก่อนครับ:

🚦 Conditional Rendering: นักควบคุมเส้นทาง (v-if vs v-show)

เมื่อเราต้องการแสดงหรือซ่อนองค์ประกอบบนหน้าเว็บตามเงื่อนไข Vue มีให้เราเลือกใช้ 2 ท่าหลักๆ:

  1. v-if, v-else-if, v-else (จอมทำลายล้างและสร้างใหม่): ทำงานเหมือนการเขียน if-else ทั่วไปเลยครับ จุดเด่นคือมันคือการ “แสดงผลแบบมีเงื่อนไขที่แท้จริง” (Real conditional rendering) หากเงื่อนไขเป็นเท็จ (False) Vue จะถอดชิ้นส่วนนั้นออกจาก DOM (Document Object Model) ไปเลย ราวกับมันไม่เคยมีอยู่บนโลกนี้
  2. v-show (ผ้าคลุมล่องหน): ต่างจาก v-if ตรงที่ v-show จะเรนเดอร์ชิ้นส่วนนั้นลงไปใน DOM เสมอ! แต่มันแค่ใช้ CSS display: none; ในการซ่อนมันเอาไว้

💡 กฎการเลือกใช้ (Rule of Thumb):

  • ใช้ v-show หากสิ่งนั้นต้องถูกสลับซ่อน/แสดงบ่อยๆ เพราะมันกินทรัพยากรน้อยกว่าเมื่อต้องเปลี่ยนสถานะ
  • ใช้ v-if หากสิ่งนั้นนานๆ จะเปลี่ยนที หรือเราไม่ต้องการให้มันถูกเรนเดอร์เลยถ้าเงื่อนไขไม่ผ่านตั้งแต่แรก (Lazy evaluation)

🔁 List Rendering: เครื่องจักรโคลนนิ่ง (v-for)

v-for คือคำสั่งที่ใช้สร้างรายการ (List) ซ้ำๆ ตามข้อมูลที่เป็น Array หรือ Object โดยมีไวยากรณ์หลักคือ item in items (หรือจะใช้คำว่า of ก็ได้) นอกจากนี้เรายังสามารถดึงลำดับ (Index) ออกมาใช้งานได้ด้วยการเขียน (item, index) in items

Diagram showing the rendering flow comparison between Conditional Rendering and List Rendering

4. 💻 ร่ายมนต์โค้ด (Show me the Code)

เรามาดูการรวมพลังของทั้ง 2 คำสั่งในการสร้างหน้ารายการสินค้ากันครับ:

<template>
  <div class="store-container">
    <h2>านคาเวทมนตร 🪄</h2>

    <!-- ใช v-if เพื่อเชควาโหลดขอมลเสรจหรอย -->
    <div v-if="isLoading" class="loading">กำลังโหลดสินค้า...</div>

    <!-- หากมี Error ค่อยโชว์ v-else-if -->
    <div v-else-if="hasError" class="error">เกิดข้อผิดพลาดในการโหลด!</div>

    <!-- ถ้าทุกอย่างปกติ (v-else) ก็ลูปข้อมูลมาแสดง -->
    <div v-else>
      <ul>
        <!-- ปขอมลดวย v-for และกำหนด :key ใหแตละชิ้ -->
        <li 
          v-for="(product, index) in activeProducts" 
          :key="product.id"
          class="product-card"
        >
          <h3>{{ index + 1 }}. {{ product.name }}</h3>
          <p>ราคา: {{ product.price }} บาท</p>
          
          <!-- ใช v-show สำหรบปุ่มที่อาจจะถกสลบไปมาบอยๆ -->
          <button v-show="product.inStock">เพิ่มลงตะกร้า</button>
          <span v-show="!product.inStock" class="out-of-stock">สินค้าหมด</span>
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const isLoading = ref(false)
const hasError = ref(false)

const products = ref([
  { id: 1, name: 'ดาบเอ็กซ์คาลิเบอร์', price: 5000, inStock: true, isActive: true },
  { id: 2, name: 'น้ำยาฟื้นพลัง', price: 150, inStock: false, isActive: true },
  { id: 3, name: 'ไม้กวาดหักๆ', price: 20, inStock: true, isActive: false } // สินค้านี้โดนระงับ
])

// 🌟 ตัวกรองสินค้า (ใช้ Computed แทนการเอา v-if ไปยัดใน v-for)
const activeProducts = computed(() => {
  return products.value.filter(product => product.isActive)
})
</script>

<style scoped>
.out-of-stock { color: red; font-size: 0.8em; }
</style>

5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips)

ในโค้ดด้านบนมี “ความลับระดับ Senior” ซ่อนอยู่ 2 อย่างที่สำคัญมากๆ ครับ:

🚨 กฎเหล็กข้อที่ 1: ห้ามใช้ v-if และ v-for ในบรรทัด (Tag) เดียวกันเด็ดขาด!

นี่คือหลุมพรางที่โปรแกรมเมอร์ตกบ่อยที่สุด! บางคนอาจจะคิดแบบนี้: (❌ โค้ดที่ผิดและพัง)

<!-- หมายเหตุ: อย่าหาทำ! -->
<li v-for="user in users" v-if="user.isActive">
  {{ user.name }}
</li>

ทำไมถึงพัง? (The Technical Reason): ในสถาปัตยกรรมของ Vue 3 v-if มีความสำคัญ (Precedence) สูงกว่า v-for ครับ! นั่นหมายความว่า จังหวะที่ Vue กำลังจะตรวจสอบเงื่อนไข v-if="user.isActive" มันจะโวยวายทันทีว่า “เฮ้ย! ไม่รู้จักตัวแปร user!” เพราะการลูป v-for ยังไม่ทันได้เริ่มต้นสร้างตัวแปร user ให้มันเลย

✅ วิธีแก้ที่ถูกต้อง (The Right Way): ให้ใช้ Computed Properties ในการกรอง (Filter) ข้อมูลเตรียมไว้ล่วงหน้า (เหมือนในโค้ดตัวอย่างข้อที่ 4 ที่เรากรอง activeProducts มารอไว้) แล้วค่อยนำ List ที่กรองแล้วมาลูปแสดงผล การทำแบบนี้ยังช่วยเรื่อง Performance ได้มาก เพราะไม่ต้องมารันการตรวจสอบเงื่อนไขทุกครั้งที่มีการ Re-render ครับ

🔑 กฎเหล็กข้อที่ 2: อย่าลืมใส่ :key เมื่อลูป v-for

น้องๆ สังเกตไหมว่าพี่ใส่ :key="product.id" ลงไปคู่กับ v-for เสมอ เหตุผลก็คือ ภายใต้การทำงานของ Virtual DOM หากข้อมูลใน Array มีการเปลี่ยนแปลง (เช่น การเรียงลำดับใหม่ หรือการแทรกข้อมูลตรงกลาง) หากไม่มี :key Vue จะใช้วิธีเปลี่ยนข้อมูลดิบๆ ใน Element เดิม (In-place patch) ซึ่งอาจทำให้ UI เอ๋อได้ หาก List ของเรามีส่วนประกอบที่ต้องจำ State (เช่น ช่อง Input)

การใส่ :key ด้วยรหัส ID ที่ไม่ซ้ำกัน เป็นการไกด์บอก Vue ให้ติดตาม (Track) องค์ประกอบแต่ละชิ้นได้อย่างแม่นยำ ทำให้แอปของเราเสถียรและเร็วขึ้นมากครับ

6. 🏁 บทสรุป (To be continued…)

v-for และ v-if เป็นเครื่องมือพื้นฐานที่ทรงพลังมาก แต่ “พลังที่ยิ่งใหญ่มาพร้อมกับความรับผิดชอบที่ใหญ่ยิ่ง” การเข้าใจจังหวะการทำงานของมัน (Lifecycle) และลำดับความสำคัญ (Precedence) จะช่วยให้น้องๆ สามารถเขียนโค้ดที่รันได้อย่างรวดเร็วและไม่มีบั๊กรบกวนใจ

เมื่อเราควบคุมการแสดงผลของข้อมูลบนหน้าจอได้แล้ว ในบทถัดไป เราจะมาเรียนรู้วิธีการ “สกัดชิ้นส่วนหน้าจอ” ให้กลายเป็น Components ซึ่งถือเป็นหัวใจสูงสุดของสถาปัตยกรรม Frontend สมัยใหม่ เตรียมตัวรับมือกับการส่งผ่านข้อมูลระหว่างพ่อกับลูก (Props & Emits) กันได้เลยครับ!


ต้องการที่ปรึกษาและพัฒนาระบบ Web Application หรือ Frontend Architecture ให้กับธุรกิจของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและพัฒนาซอฟต์แวร์แบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p