Vue.js เริ่มต้น ตอน10 (Vuex)

23 Sep 2018

Share to:

Vuex คืออะไร

Vuex เป็นตัวช่วยจัดการ Data flow โดยปกติเวลาเขียนเว็บจะต้องมีการใช้งาน State หรือ Data ที่เก็บข้อมูลใน Component อยู่แล้ว ซึ่ง Vuex จะมาช่วยจัดการอะไรพวกนี้  ทําให้ Code ของเราเป็นระบบ และ ข้อมูลทั้งหมดจะไหลไปในทิศทางเดียวกันทั้งระบบ ลดการเขียน Code ซํ้าซ้อน

Vuex ช่วยจัดการ Data flow อย่างไร

ก่อนอื่นมาดูความแตกต่างระหว่างไม่ใช้ Vuex กับใช้ Vuex ตามรูปนี้

Image

จากรูป รูปวงกลมๆแทน Component ลูกศรคือการส่ง Data กันระหว่าง Component

รูปฝั่งซ้ายเป็นการจัดการ Data โดยไม่ใช้ Vuex คือ Component ส่งข้อมูลไปมาหากันโดยตรง ทําให้ข้อมูลกระจายไปอยู่ตาม Component ต่างๆ สิ่งที่เกิดขึ้นคือ Flow ของข้อมูลไม่ไหลไปในทิศทางเดียวกัน ทําให้เราติดตามข้อมูลได้ยาก

รูปฝั่งขวาคือการจัดการ Data โดย Vuex คือ Data ทั้งหมดจะถูกเก็บไว้ใน Store ที่เดียว Component ไหนจะใช้ก็ข้อมูลก็ไปหยิบมาใช้ และ Component ไหนต้องการเปลี่ยนข้อมูลก็ไปเปลี่ยนที่ Store ซึ่งการทํางานของ Vuex อธิบายตามรูปด้านล่าง

Image

จากรูป การทํางานของ Vuex จะเริ่มต้นจากเกิด Event บางอย่าง ที่ Vue Components เช่น กดปุ่ม  แล้ว Vue Component จะ Dispatch ไปยัง Action เพื่อทํา Action บางอย่าง เช่น ไปดึงข้อมูลจาก Backend API เพื่อมา Commit ไปยัง Mutations หลังจากนั้นก็จะ Change ข้อมูล(Mutate) ที่อยู่ใน State เมื่อ State เปลี่ยนก็จะ Render Component ใหม่เพื่อเปลี่ยนแปลงข้อมูลใน Component ต่างๆที่หยิบเอาข้อมูลไปใช้

จะเห็นว่าข้อมูลไหลไปในทิศทางเดียว และเก็บไว้ที่เดียว ถ้าสังเกตดีๆ จะเห็นว่าข้อมูลที่อยู่ใน State จะเปลี่ยนแปลงได้ก็ต่อเมื่อเกิด Action เท่านั้น ทําให้เราสามารถติดตามข้อมูลได้ง่าย ข้อมูลตรงไหนผิด ก็ไปดูที่ Action ได้เลย

ส่วนประกอบของ Vuex

Vuex เป็น library สําหรับสร้าง Store ขึ้นมา โดยในแต่ละ Store จะประกอบไปด้วย 4 ส่วนหลักๆดังนี้

State

State เป็นที่สําหรับเก็บข้อมูลของ Store ซึ่งเราสามารถ Design รูปแบบของการเก็บได้ตามต้องการ

Getters

Getters จะใช้ในกรณีที่ต้องการ Process อะไรบางอย่างก่อนที่จะทําข้อมูลใน Store ไปใช้ พูดง่ายๆ ก็จะคล้ายๆกับ Computed

Action

Action เป็นส่วนที่ทํา Action ต่างๆ เช่น ไปดึงข้อมูลจาก Backend API หรือทํา Business flow อะไรบางอย่าง แล้วจึง commit ไปยัง Mutation(จะ Commit หรือไม่ Commit ก็ได้ ขึ้นอยู่กับ Flow ของเว็บที่ออกแบบไว้)

Mutations

Mutations เป็นส่วนในการเปลี่ยนแปลงข้อมูลของ State ใน Store ที่ได้รับการ Commit มาจาก Action

การใช้งาน Vuex

เพื่อให้ง่ายต่อความเข้าใจ ผมจะยกตัวอย่างเว็บหน้าตาประมาณนี้ครับ

Image

จากรูปด้านบนเราจะสร้าง Component ขึ้นมา 3 Cpmponent โดยแต่ละ Component มีหน้าที่ดังนี้

  • Component A ทําหน้าที่แสดงผลข้อมูล
  • Component B จะมีปุ่ม INCREASE COUNTER ไว้เพิ่มค่า Counter
  • Component C จะมี form สําหรับบันทึกชื่อ และนามสกุล

จากหน้าตาของ UI ด้านบนเราจะออกแบบ Store ของเราได้ดังนี้ คือเราจะแยก Store ออกเป็นสอง Module

  • name สําหรับเป็นค่า ชื่อ และนามสกุล
  • counter สําหรับเก็บค่า counter

การทํางานของเว็บนี้คือ Component A จะเอาข้อมูลจาก Store name และ Counter ออกมาแสดงผล Component B จะทําหน้าที่ไปเพิ่มค่า Counter ที่อยู่ใน Store counter ส่วน Component C จะทําหน้าที่เปลี่ยนข้อมูล ซื้อ และนามสกุล ที่เก็บอยู่ใน Store name

ในการใช้งาน Vuex เราจะต้องสร้าง Store ขึ้นมาจาก Vuex โดยอันดับแรกสร้าง Folder Store และมี File ดังรูปครับ

Image

จากรูปแต่ละ file จะมีหน้าที่ดังนี้

  • index.js เป็น File ที่ใช้สร้าง Store โดยจะร่วมทุกๆ Store module เข้าด้วยกัน
  • modules/counter เป็น Store module counter
  • modules/name เป็น Store module name

มาดูที่ file index.js ก่อนครับ

import Vue from 'vue'
import Vuex from 'vuex'
import counter from './modules/counter'
import name from './modules/name'

Vue.use(Vuex)

const debug = process.env.NODE_ENV !== 'production'

export default new Vuex.Store({
  modules: {
    counter,
    name
  },
  strict: debug
})

จาก code ด้านบน เราได้ Import file counter และ name เข้ามาเพื่อใช้ Vuex สร้างเป็น Store ขึ้นมาแล้ว Export ออกไป แล้วเราจะเอาไปใช้ในขั้นตอนต่อไป

ส่วนภายใน File counter และ name เราจะประกอบไปด้วย state, getters, action, mutations ตามตัวอย่างดังนี้

modules/counter.js

const state = {
  currentCounter: 0
}

const getters = { }

const actions = {
  increaseCounter: ({ commit, state }, payload) => {
    commit('INCREASE_CURRENT_COUNTER')
  }
}

const mutations = {
  INCREASE_CURRENT_COUNTER (state, payload) {
    state.currentCounter++
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
}

modules/name.js

const state = {
  firstName: 'Thiti',
  lastName: 'Yamsung'
}

const getters = {
  fullName: (state, getters, rootState) => {
    return state.firstName + ' ' + state.lastName
  }
}

const actions = {
  setName: ({ commit, state }, payload) => {
    commit('SET_FIRST_NAME', payload.firstName)
    commit('SET_LAST_NAME', payload.lastName)
  }
}

const mutations = {
  SET_FIRST_NAME (state, payload) {
    state.firstName = payload
  },
  SET_LAST_NAME (state, payload) {
    state.lastName = payload
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
}

อธิบาย Code ในส่วนของ Action

ใน Action Vuex จะส่ง commit, state และ payload มาให้เราด้วยซึ่งเราสามารถนํามาใช้ประโยชน์ได้ดังนี้

  • commit เราจะใช้ในการเรียก Mutation ขึ้นมาทํางานโดยจะระบุเป็นชื่อของ Mutation และสามารถส่งข้อมูลไปด้วยได้ (Mutation จะได้รับข้อมูลเข้ามาผ่านทาง payload)
  • state เป็น state ปัจจุบัน
  • payload คือ ข้อมูลที่รับเข้ามา เมื่อเราเรียก Action นี้ขึ้นมาทํางาน

อธิบาย Code ในส่วนของ Mutation

ใน Mutation Vuex จะส่ง state, payload มาให้เราด้วยซึ่งเราสามารถนํามาใช้ประโยชน์ได้ดังนี้

  • state เป็น state ปัจจุบัน
  • payload คือ ข้อมูลที่รับเข้ามา เมื่อเราเรียก Mutaion นี้ขึ้นมาทํางาน

มาถึงตรงนี้เราได้ Store ขึ้นมาลอยๆอยู่ Vue ของเรายังไม่รู้จัก ขั้นตอนต่อไปเราจะเอา Store นี้เข้าไปใช้งานใน Vue โดยเข้าไปที่ File src/main.js แล้วเพิ่ม Code เข้าไปดังนี้

import Vue from 'vue'
import App from './App.vue'
import Vuetify from 'vuetify'
import store from './store'

import 'vuetify/src/stylus/main.styl'

Vue.use(Vuetify)

Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

จาก Code ด้านบนเรา Import store ที่เราสร้างไว้ตอนต้น แล้วมาเพิ่มเข้าไปในขั้นตอนการสร้าง Vue Instance (new Vue(store, …)) เท่านี้เราก็จะสามารถใช้งาน Store ใน Vue ของเราได้แล้ว

ต่อไปเราจะมาดูวิธีการใช้ mapGetters, mapState, mapAction

mapGetters()

mapGetters() เป็น function สําหรับ map getter ใน Store ของเราเข้ามาเป็น Computed เพื่อให้เราสามารถเรียกใช้งานใน Component ได้ง่ายๆ ตัวอย่างดังนี้

import {mapGetters} from 'vuex'

export default {
  name: 'A',
  computed: {
    ...mapGetters({
      fullName: 'name/fullName'
    })
  }
}

ในตัวอย่างนี้เราดึง getter fullName ใน Store module name ออกมาใช้งาน

mapState()

mapState() เป็น function สําหรับ map state ใน Store ของเราเข้ามาเป็น Computed เพื่อให้เราสามารถเรียกใช้งานใน Component ได้ง่ายๆ ตัวอย่างดังนี้

import {mapState} from 'vuex'

export default {
  name: 'A',
  computed: {
    ...mapState({
      currentCounter: store => store.counter.currentCounter
    })
  }
}

ในตัวอย่างนี้เราดึง state currentCounter ใน Store module counter ออกมาใช้งาน

mapAction()

mapAction() เป็น function สําหรับ map action ใน Store ของเราเข้ามาเป็น Methods เพื่อให้เราสามารถเรียกใช้งานใน Component ได้ง่ายๆ ตัวอย่างดังนี้

import {mapActions} from 'vuex'

export default {
  name: 'B',
  methods: {
    ...mapActions({
      increaseCounter: 'counter/increaseCounter'
    })
  }
}

ในตัวอย่างนี้เราดึง action increaseCounter ใน Store module counter ออกมาใช้งาน

เท่านี้เราสามารถใช้งาน Action, state, getter ในทุกๆ Component ของเราได้เลยครับ

สามารถโหลด Project ตัวอย่างเต็มๆ มาลองเล่น ได้ที่นี่ github.com/mrthiti/vuex-example

Suggestion blogs

Vue.js เริ่มต้น ตอน5 (ทําความรู้จักกับ Props)

หลังจากที่เราเรียนรู้ Component กันไปแล้ว ถ้ายังจํากันได้ภายใน Component มี Option ตัวนึงชื่อว่า Props ซึ่งมีหน้าที่ รับข้อมูลจากภายนอก Component เข้ามาใช้งานภายใน Component โดยจะรับข้อมูลผ่านทาง Attribute การใช้งาน Props สามารถใช้งานได้หลายรูปแบบ เราจะมาเรียนรู้ไปทีละแบบนะครับ

IPFS คืออะไร

IPFS ย่อมาจาก Interplanetary File System เป็นเว็บแบบกระจายตัว หรือ Decentralized Content Gateway และ IPFS เป็นระบบไฟล์แบบ peer-to-peer คล้ายๆ Blockchain โดยจะกระจายไฟล์ไปเก็บไว้ยังเครื่องคอมพิวเตอร์ที่ทําหน้าที่เป็น Node ทั่วโลก แทนที่จะเก็ไฟล์ไว้ใน Server หรือคอมพิวเตอร์เพียงเครื่องเดียว ทําให้ไฟล์ยังคงอยู่ตลอดไปตามใดที่ยังมีคนสนใจไฟล์นั้น และเก็บไฟล์นั้นไว้

การใช้งาน Neo Pixel WS2812B กับ Raspberry pi2

ในบทความที่แล้ว เราทำความรู้จักกับ Neo Pixel WS2813 กันไปแล้ว วันนี้ผมจะมาแนะนำเรื่อง การนำ Raspberry Pi2 มาควบคุม Neo Pixel WS2812B


Copyright © 2019 - 2024 thiti.dev |  v1.41.0 |  Privacy policy | 

Build with ❤️ and Astro.

Github profile   Linkedin profile   Instagram   X profile   Youtube channel   Telegram   Email contact   วงแหวนเว็บ