ข้ามไปเนื้อหาหลัก

ทำไม JavaScript ควรจัดการ State แทนที่จะคุมสไตล์ CSS

เจาะลึกแนวคิดจากไลบรารี quell-light.js ว่าด้วยการแยกแยะ State กับ Style ผ่าน data-* attributes เพื่อลดความเปราะบางของโค้ดในระยะยาว

เรียบเรียงโดย AI
Inewgen
08 Sep 2026ที่มา: Dev.to4 นาทีอ่าน (0 ครั้ง)
แชร์
ทำไม JavaScript ควรจัดการ State แทนที่จะคุมสไตล์ CSS

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง

ขนาดตัวอักษร
  • หลีกเลี่ยงการใช้ inline styles หรือคลาส CSS แบบเดิมในการควบคุมสถานะ
  • การใช้ naming convention เช่น is- หรือ has- มีความเปราะบางในระยะยาว
  • ไลบรารี quell-light.js นำเสนอการใช้ data-* attributes เช่น data-q-active เพื่อบอกสถานะอย่างชัดเจน
  • แยกการจัดการพฤติกรรมและสถานะออกจากรูปร่างหน้าตาที่ CSS ดูแลทั้งหมด

เมื่อเราต้องการเปิดเมนูดรอปดาวน์ แสดงหน้าต่างโมดอล หรือระบุลิงก์เมนูนำทางที่ผู้ใช้งานกำลังเปิดดูอยู่ในปัจจุบัน วิธีการดั้งเดิมที่นักพัฒนาหลีกเลี่ยงกันแล้วคือการใช้คำสั่งควบคุมสไตล์ตรงๆ เช่น element.style.display = 'block' ซึ่งรวมตรรกะของสถานะและการแสดงผลไว้ในบรรทัดเดียวกัน ทางเลือกที่พบเห็นได้ทั่วไปในปัจจุบันจึงเป็นการสลับคลาส CSS แทน เช่น การใช้คำสั่ง classList.toggle('is-open') ซึ่งถือเป็นการยกระดับที่ดีขึ้น เนื่องจากเปิดให้ CSS เป็นผู้กำหนดหน้าตาของคลาส .is-open ทั้งหมด ขณะที่ JavaScript ทำหน้าที่เพียงสลับว่าคลาสนี้ควรปรากฏอยู่หรือไม่เท่านั้น

อย่างไรก็ตาม ปัญหาที่ซ่อนอยู่คือคลาส .is-open นั้นถูกดึงมาจากเนมสเปซเดียวกันกับฮุกสำหรับจัดแต่งสไตล์อื่นๆ ทั้งหมดในโค้ดเบส ไม่มีเครื่องหมายทางไวยากรณ์ใดที่บ่งบอกว่าคลาสนี้คือสถานะ (state) ไม่ใช่รูปแบบการแสดงผล (appearance) ส่งผลให้เพื่อนร่วมทีมในอนาคตไม่สามารถแยกแยะระหว่าง .is-open กับ .card-title ได้เลย เว้นแต่จะเข้าใจความหมายจากชื่อและเชื่อมั่นว่าข้อตกลงร่วมกันของทีมจะยังคงอยู่

การพึ่งพาข้อตกลงร่วมกัน (convention-based boundaries) ภายในทีม เช่น การตกลงกันว่าคลาสที่ขึ้นต้นด้วย is- หรือ has- คือสถานะ มักจะใช้งานได้ดีในทีมที่มีวินัยสูงและสมาชิกหน้าเดิมยังอยู่ครบถ้วน อย่างไรก็ตาม แนวทางนี้มีความเปราะบางสูงเมื่อทีมมีขนาดใหญ่ขึ้น มีพนักงานเข้าออก หรือเมื่อโค้ดเบสเติบโตขึ้นจนไม่มีใครสามารถจดจำกฎเกณฑ์ทั้งหมดได้ การย้ายขอบเขตนี้ไปสู่ระดับไวยากรณ์จึงช่วยแก้ปัญหาความเข้าใจคลาดเคลื่อนได้อย่างยั่งยืน

ไลบรารี quell-light.js ได้ก้าวไปอีกขั้นนอกเหนือจากเรื่องข้อตกลง โดยระบุจุดยืนไว้อย่างชัดเจนตั้งแต่วันแรกว่าไม่ใช่คอมโพเนนต์ไลบรารี ไม่ได้ทำหน้าที่เรนเดอร์สิ่งใด และมีหน้าที่หลักเพียงอย่างเดียวคือการรักษาเสถียรภาพด้านพฤติกรรม สิ่งที่น่าสนใจคือทางเลือกที่นำมาใช้แทนคลาสสถานะทั่วไป นั่นคือการทำให้ State ถูกแสดงออกมาในรูปแบบของ State ทางไวยากรณ์อย่างแท้จริง ไม่ใช่แค่พึ่งพาข้อตกลงร่วมกัน

แม้คลาสจะสามารถทำหน้าที่นี้ได้ แต่การใช้ data-* attributes เช่น data-q-active นั้นมีความชัดเจนมากกว่าในเชิงความหมาย เนื่องจากแอตทริบิวต์ตระกูล data-* ไม่มีผลต่อการจัดแต่งสไตล์ในตัวเอง จึงไม่สามารถถูกเข้าใจผิดว่าเป็นยูทิลิตี้คลาส ไม่เข้าไปพึ่งพิงการแย่งชิงความเฉพาะเจาะจงของ CSS และไม่ขึ้นอยู่กับข้อตกลงในการตั้งชื่อของทีมที่อาจเปลี่ยนแปลงตามกาลเวลา โดยคำศัพท์เกี่ยวกับสถานะทั้งหมดของ quell-light.js ประกอบด้วย data-q-toggle, data-q-active, data-q-dismiss, data-q-spy และ data-q-current ซึ่งทำหน้าที่อธิบายเฉพาะสิ่งที่เกิดขึ้นจริง โดยไม่มีคำใดอธิบายเรื่องรูปร่างหน้าตาเลย

ไม่อยากพลาดข่าวใหม่?

สมัครรับสรุปข่าวสารใหม่ทางอีเมล ไม่บ่อยจนรำคาญ

โฆษณา

frontend web development code editor laptop screen

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง

โมดูลการทำงานภายในไลบรารีนี้ยังพิสูจน์ให้เห็นว่าแนวทางดังกล่าวสามารถรองรับข้อกำหนดด้านการเข้าถึง (accessibility) ที่ซับซ้อนได้จริง ตัวอย่างเช่น การจัดการโฟกัสที่บังคับใช้การดักจับปุ่ม Tab และ Shift+Tab ภายในหน้าต่างไดอะล็อกที่เปิดอยู่ พร้อมทั้งติดตามองค์ประกอบที่จะคืนค่าโฟกัสเมื่อปิดหน้าต่าง ซึ่งทั้งหมดนี้คือสถานะที่แท้จริง ขณะที่รูปร่างหน้าตาของไดอะล็อกถูกปล่อยให้ CSS เป็นผู้จัดการ นอกจากนี้ ระบบติดตามการเลื่อนหน้าเว็บยังเลือกใช้ IntersectionObserver แทนการฟังเหตุการณ์ scroll แบบดิบๆ เพื่อตัดสินใจว่าส่วนใดกำลังทำงานอยู่ แล้วแสดงผลผ่านแอตทริบิวต์ aria-current บนลิงก์นำทาง

แนวทางของ quell-light.js จึงไม่ได้เป็นการหลีกเลี่ยงข้อผิดพลาดทั่วไป แต่เป็นการเลือกใช้งานแนวทางที่ชัดเจนและรัดกุมยิ่งขึ้นสำหรับสิ่งที่มีมูลค่าควรทำอยู่แล้ว ข้อมูลจากบทความนี้สะท้อนให้เห็นว่าขอบเขตที่ถูกเข้ารหัสไว้โดยตรงในไวยากรณ์ย่อมมีความทนทานและพึ่งพาได้มากกว่าขอบเขตที่ค้ำจุนด้วยความจำของทีมงาน

ที่มา: Dev.to

ความคิดเห็น

แสดงความคิดเห็น
0/2000

พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้