MVVM ( Model-View-ViewModel ) คือสถาปัตยกรรมที่ถูกสร้างขึ้นมาเพื่อลดภาระความเหนื่อยล้าในการเขียนโค้ดสั่งงานหน้าจอที่เราเจอกันใน MVP ครับ
ใน MVP เรามี Presenter ที่ต้องคอยสั่ง View แบบละเอียดยิบ ( เช่น “View เอ้ย ช่วยเปลี่ยนข้อความบรรทัดนี้หน่อย”, “View ช่วยซ่อนปุ่มนี้ที” ) พอระบบใหญ่ขึ้น โค้ดสั่งงานพวกนี้จะยาวและน่าเบื่อมาก
MVVM เลยเอาเวทมนตร์ที่เรียกว่า Data Binding ( การผูกข้อมูล ) เข้ามาช่วยแก้ปัญหานี้ครับ โดยแบ่งการทำงานออกเป็น 3 ส่วนดังนี้:
- Model ( ข้อมูลและตรรกะ )
ยังคงทำหน้าที่เหมือนเดิมทุกประการครับ คือจัดการกับข้อมูล การคำนวณ ติดต่อฐานข้อมูล หรือเรียก API โดยไม่สนใจหน้าจอเลย - ViewModel ( ตัวแทนของหน้าจอ )
หน้าที่ของมันคล้าย Presenter คือการดึงข้อมูลจาก Model มาเตรียมไว้ให้หน้าจอ แต่จุดที่ต่างกันโดยสิ้นเชิงคือ ViewModel จะ “ไม่รู้จัก View” เลยครับ มันไม่มีฟังก์ชันในการสั่งงาน View ไม่มีการจับคู่กันโดยตรง หน้าที่ของมันมีแค่เก็บ “สถานะ ( State )” หรือข้อมูลล่าสุดของหน้าจอนั้น ๆ เอาไว้ เช่นcount = 0หรือisLoading = true - View ( หน้าจอและการผูกข้อมูล )
หน้าตา UI ของระบบ ( เช่น HTML / CSS ) ใน MVVM ตัว View จะมีความฉลาดเพิ่มขึ้นมานิดหน่อยตรงที่มันสามารถ “ผูก ( Bind )” ตัวเองเข้ากับตัวแปรใน ViewModel ได้
หัวใจสำคัญ: การทำงานของ Data Binding
ความมหัศจรรย์ของ MVVM อยู่ที่กลไกอัตโนมัตินี้ครับ เมื่อ View ผูกข้อมูลเข้ากับ ViewModel แล้ว
- ถ้าข้อมูลใน ViewModel เปลี่ยน: View จะอัปเดตหน้าจอตัวเองโดยอัตโนมัติทันที! ( ไม่ต้องมีใครไปสั่งมัน )
- ถ้าผู้ใช้พิมพ์ข้อมูลลงใน View: ข้อมูลใน ViewModel ก็จะถูกอัปเดตตามไปพร้อม ๆ กันแบบเรียลไทม์ ( Two-way Data Binding )
เปรียบเทียบให้เห็นภาพง่าย ๆ
- MVP: Presenter ต้องสั่งงานว่า
document.getElementById('text').innerText = "Hello";( สั่งงานตรง ๆ ) - MVVM: ViewModel แค่ประกาศตัวแปรว่า
this.text = "Hello";แล้วเดี๋ยวกลไก Data Binding ของ Framework ( เช่น Vue.js, Angular, React ) จะเอาคำว่า Hello ไปแปะบนหน้าจอให้เองแบบอัตโนมัติ!
ตัวอย่างโค้ด Counter ด้วย MVVM ( สไตล์ Vue.js )
ลองเทียบกับโค้ด MVP ก่อนหน้านี้นะครับ จะเห็นว่าสั้นลงมหาศาล เพราะเราไม่ต้องเขียนโค้ดจับคู่ปุ่มหรือสั่งเรนเดอร์หน้าจอเองเลย
ฝั่ง View ( HTML )
<div id="app">
<h1>จำนวนปัจจุบัน: {{ count }}</h1>
<button @click="increment">Add</button>
</div>
ฝั่ง ViewModel ( JavaScript )
// ViewModel แค่สนใจการจัดการ Data ตัวเอง ไม่มีการไปยุ่งกับ DOM เลย
const app = Vue.createApp({
data() {
return {
count: 0 // เก็บ State
}
},
methods: {
increment() {
this.count++; // แค่บวกเลข เดี๋ยวหน้าจอ HTML จะอัปเดตเลขนี้เองอัตโนมัติ!
}
}
});
app.mount('#app');
สรุปข้อดีหลัก ๆ ของ MVVM: โค้ดสั้นลงมาก, แยกการทำงานระหว่างคนทำ UI กับคนเขียน Logic ได้เด็ดขาด, และตัว ViewModel นำไปเขียน Unit Test ได้ง่ายสุด ๆ เพราะไม่มีโค้ดที่เกี่ยวกับหน้าจอ (DOM) ปนอยู่เลยครับ
อ่านเพิ่มเติม
