Home » Vuejs » มาทำ Data two-way binding ใน vue.js 2 กัน ตอน 1
Cr. Itthipat.me

เกริ่นชื่อหัวข้อมาก็ปวดหัวแล้วเรามาเริ่มกันเลยดีกว่า ในการใช้งาน Freamwork ที่เป็น Base on Component นั้นเราต้องแยกไฟล์เป็นส่วนประกอบย่อยๆแล้วเอามารวมกันเป็นหน้า 1 หน้าที่นี้เวลาเราแยก component ออกไปเราก็ทำการส่งค่า props ไปหา component ลูกแบบนี้

<child-component :name="name"></child-component>

ง่ายใช่มั้ยละ (วิธีรับค่า props แบบปกติคงไม่ขอพูดถึงในบทความนี้เดี๋ยวจะยาว) แต่ถ้าเกิดใน child component มันดันเป็น input field, textarea, etc. ที่มันกรอกข้อมูลได้เราจะส่งมันกลับมายังไง ติ๊กต๊อกๆ..เห้ยทำยังไงนั่นคือคำถามแรกในหัวผมเลยเพราะปกติเราก็ส่ง props ไปหาตลอดไม่เคยให้ child คืนข้อมูลกลับมาเลยนอกจากการ emit เมื่อกดปุ่มแต่นี่เราต้องการให้พิมพ์แล้วข้อความมันส่งกลับมาเลยโดยไม่ต้องกดปุ่มอะไร

เอาล่ะมาดูวิธีการกันในตัวอย่างผมขอแบ่ง Component เป็น 3 ชั้นดังนี้

<template>
  <div>
    <h1>Todo List</h1>
    <todo-list></todo-list>
  </div>
</template>
<script>
import TodoList from './TodoList'
export default {
components: {
    TodoList
  }
  
}
</script>

ไฟล์นี้ทำการ import ตัว component todo-list เข้ามาปกติหลายคนอาจจะงงว่ามันมีทำไมในเมื่อเอาไปรวมกับ TodoList.vue ได้ อย่าลืมนะครับว่าเราควรแบ่ง component ให้เล็กที่สุดและอีกอย่างตัว layout นี้แหละที่ใช้เป็นตัว call API (แต่บทความนี้ไม่ขอพูดถึงจ้า) และส่งลงไปให้ child-component

<template>
  <div class="container">
    <div class="field-warp">
      <field-list v-model="description"></field-list>
    </div>
    <pre>{{ description }}</pre>
  </div>
</template>
<script>
import FieldList from './FieldList'
export default {
components: {
    FieldList
  },
data() {
    return {
      description: 'Hello'
    }
  }
  
}
</script>
<style>
.container {
  width: 960px;
  margin: 0 auto;
  text-align: center;
}
.field-warp {
  display: block;
}
</style>

ในไฟล์ TodoList.vue เราทำการเรียก component FieldList อีกต่อเพื่อจะนำ input ออกมา และ ทำการ print ค่าตัวแปร description ใน pre เพื่อดูว่า component FieldList จะสามารถส่งค่ากลับมาได้หรือไม่

<template>
  <input type="text" :value="value" placeholder="Description" @input="updateValue($event.target.value)">
</template>
<script>
export default {
props: ['value'],
  
  methods: {
    updateValue(value) {
      this.$emit('input', value)
    }
  }
}
</script>

component นี้เป็น input ธรรมดาเราจะมาดูกันว่าทำอย่างไรเมื่อเราต้องการให้ส่ง props ไปหา field-list และ ส่งกลับมาด้วยตัวแปรเดียวกัน

สังเกตุที่ไฟล์ TodoList.vue มีการส่ง v-model เข้าไปใน component

<field-list v-model="description"></field-list>

และในส่วนของ FieldList.vue จะไม่ได้รับ props แบบปกติแล้วเพราะเราไม่ได้ส่งอะไรเข้าไปแต่เราใช้ v-model ส่งทั้งตัวแปรและรับค่าเลยเราจึงต้องรับ props ชื่อ “value” เท่านั้นตาม Doc เลย

props: ['value'] // รับค่ามาจาก v-model="description"

และนำค่า value ไป bind ใส่ attribute value ของ input จากนั้นเมื่อเกิด event input ขึ้นให้ส่ง $event.target.value (ค่า value จากตัว input) ไปที่ฟังก์ชั่นแล้วทำการ $emmit ไปที่ event “input” มันจะส่งค่ากลับไปเข้าตัว v-modal=”description” อัตโนมัติเลย

<input type="text" :value="value" placeholder="Description" @input="updateValue($event.target.value)">
<script>
export default {
props: ['value'],
  
  methods: {
    updateValue(value) {
      this.$emit('input', value)
    }
  }
}
</script>

จะได้หน้าตาแบบนี้

แต่เรื่องนี้มันไม่จบง่ายแบบนี้แน่ๆเพราะถ้ามันง่ายขนาดนี้จะมาเขียนบทความให้เมื่อยตัวทำไมเพราะในเมื่อ component FieldList ผมต้องการให้มี input มากกว่า 1 !!……

มาดู Requirement กันก่อน

  1. ต้องมีปุ่มกด ADD เมื่อกดแล้วจะเพิ่ม FieldList ขึ้นมา
  2. ใน FieldList นั้นจะมี 2 input หรือ มากกว่า

ในตอนแรกผมคิดหัวแทบแตกจะเขียนอย่างไรโดยใช้แค่ vue.js ไม่อยากไปใช้ jquery หรือ pure javascript เพื่อ access DOM เพราะไหนๆ vue.js มันก็ก็อบของดีอื่นๆมาตั้งเยอะมันต้องทำอะไรได้บ้างแหละจนพบ DOC เรื่อง Sync อ่านลงมาเรื่อยๆก็ได้ concept ตามด้านบนที่ได้เล่าไปแต่ทำไมมันไม่มี emit event ที่พ่น value ออกมาพร้อมกันเยอะๆพยายามหาบทความว่ามี v-model แบบ multiple value บ้างมั้ยจนหมดหนทาง ก็เลยไปถามกลุ่ม Vue.js Thailand ก็ได้แนวคิดและเอามารวมกับที่นั่งอ่านก็ได้ปิ๊งไอเดียในการทำ…….แต่ตอนนี้บทความมันยาวไปซะแล้วเดี๋ยวผมจะขอต่อใน path 2 นะครับ

ตอนที่ 2 มาแล้ว!!

เกี่ยวกับผู้เขียน

Itthipat Thitsarak

สวัสดีครับผม อิทธิพัทธ์ (เป้) เป็น Freelance Web developer ชอบหาเทคนิคต่างๆที่ทำให้ชีวิต Programmer ง่ายขึ้นโดย Blog นี้จะ สอน Laravel, Vuejs, CSS, HTML 5 และอื่นๆ ที่เกี่ยวกับการทำเว็บไซต์

ขอบคุณทุกคนที่ติดตาม และอ่านบทความของผมครับ หากใครมีคำถามหรืออยากให้ผมเขียนเกี่ยวกับเรื่องอะไรเพิ่มเติม สามารถแสดงความคิดเห็นไว้ที่ใต้บทความ หรือส่งเรื่องเข้ามาที่ Email ได้เลยครับ หัวข้อไหนน่าสนใจ ผมจะหยิบมาเขียนบทความให้ได้อ่านกันเรื่อยๆครับ

Scroll to Top