點燈坊

失くすものさえない今が強くなるチャンスよ

WebSocket + Vuex 初體驗

Sam Xiao's Avatar 2023-10-17

WebSocket 在實務上常用於全域的通知,因此大都搭配 Vuex 架構使用 WebSocket。

Version

Vue 2.6
Vuex 3.6

Vuex

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    connection: {},
    message: '',
  },
  mutations: {
    setConnection(state, payload) {
      state.connection = payload
    },
    setMessage(state, payload) {
      state.message = payload
    }
  },
})

Line 7

state: {
  connection: {},
  message: '',
},
  • 將原本在 dataconnectionmessage 改儲存在 Vuex 的 state
  • connection:儲存 WebSocket object
  • message:儲存 WebSocket 所傳送要顯示的訊息

Line 11

mutations: {
  setConnection(state, payload) {
    state.connection = payload
  },
  setMessage(state, payload) {
    state.message = payload
  }
},
  • 建立 mutation 寫入 connectionmessage

Vue

App.vue

<template>
  <div>
    <div>
      <button @click="onSendMessage">
        Send Message
      </button>
    </div>
    <div>
      {{ message }}
    </div>
  </div>
</template>

<script>
import store from '@/store'

export default {
  mounted() {
    let connection = new WebSocket('wss://free.blr2.piesocket.com/v3/1?api_key=jW7aQvkMadLuZg6wdxAJsOeGHlGX8p3urLLBrZoH&notify_self=1')

    connection.onmessage = msg => {
      console.warn('receive msg', msg)
      store.commit('setMessage', msg.data)
    }

    connection.onopen = () => {
      console.warn('connected to websocket server')
    }

    store.commit('setConnection', connection)
  },
  methods:{
    onSendMessage() {
      let msg = 'Hello'
      console.warn('send message', msg)
      store.state.connection.send(msg)
    }
  },
  computed:{
    message() {
      return store.state.message
    }
  }
}
</script>

Line 18

mounted() {
  let connection = new WebSocket('wss://free.blr2.piesocket.com/v3/1?api_key=jW7aQvkMadLuZg6wdxAJsOeGHlGX8p3urLLBrZoH&notify_self=1')

  connection.onmessage = msg => {
    console.warn('receive msg', msg)
    store.commit('setMessage', msg.data)
  }

  connection.onopen = () => {
    console.warn('connected to websocket server')
  }
  
  store.commit('setConnection', connection)
},
  • 直接使用 new 建立 WebSocket object
  • 使用免費的 PieSocket 測試 WebSocket
  • 當 WebSocket object 建立成功後,會發起 open event,可在此確定 WebSocket 是否建立成功
  • WebSocket 所回傳訊息會觸發 message event,可在此接受 WebSocket 所回傳訊息,並透過 store.commit() 寫入 message state
  • 最後將 WebSocket object 透過 store.commit() 寫入 connection state

PieSocket 必須 註冊 取得 api key 才能使用,並設定 notify_self1 才能回傳所送出的訊息

Line 33

onSendMessage() {
  let msg = 'Hello'
  console.warn('send message', msg)
  store.state.connection.send(msg)
}
  • 夠過 Vuex 內的 connection state 的 send() 送出訓訊息給 WebSocket

Line 39

computed:{
  message() {
    return store.state.message
  }
}
  • 使用 message computed 接收 mssage state 所傳來的訊息

Conclusion

  • 若收到 WebSocket 後 header 必須改變,由於 header 為 component 在每個 page 都有,因此只能寫成 Vuex 架構才能讓 header 在每個 page 都能更新