native websocket implementation for Vuejs 3 and Vuex4
yarn add vue-native-websocket
# or
npm install vue-native-websocket --save
Automatic socket connection from an URL string
import VueNativeSock from 'vue-native-websocket'
app.use(VueNativeSock, 'ws://localhost:9090')
Enable Vuex integration, where './store'
is your local apps store:
import store from './store'
app.use(VueNativeSock, 'ws://localhost:9090', { store: store })
Set sub-protocol, this is optional option and default is empty string.
import VueNativeSock from 'vue-native-websocket'
app.use(VueNativeSock, 'ws://localhost:9090', { protocol: 'my-protocol' })
Optionally enable JSON message passing:
app.use(VueNativeSock, 'ws://localhost:9090', { format: 'json' })
JSON message passing with a store:
import store from './store'
app.use(VueNativeSock, 'ws://localhost:9090', { store: store, format: 'json' })
Enable ws reconnect automatically:
app.use(VueNativeSock, 'ws://localhost:9090', {
reconnection: true, // (Boolean) whether to reconnect automatically (false)
reconnectionAttempts: 5, // (Number) number of reconnection attempts before giving up (Infinity),
reconnectionDelay: 3000, // (Number) how long to initially wait before attempting a new (1000)
})
Manage connection manually:
app.use(VueNativeSock, 'ws://localhost:9090', {
connectManually: true,
})
const vm = createApp(...)
// Connect to the websocket target specified in the configuration
vm.$connect()
// Connect to an alternative websocket URL and Options e.g.
vm.$connect('ws://localhost:9090/alternative/connection/', { format: 'json' })
// do stuff with WebSockets
vm.$disconnect()
{
methods: {
clickButton: function(val) {
// $socket is [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) instance
this.$socket.send('some data')
// or with {format: 'json'} enabled
this.$socket.sendObj({awesome: 'data'})
}
}
}
Create a new listener, for example:
this.sockets.onmessage = (data) => console.log(data)
Remove existing listener
delete this.sockets.onmessage
Vuex integration works differently depending on if you've enabled a format
Socket events will commit mutations on the root store corresponding to the following events
SOCKET_ONOPEN
SOCKET_ONCLOSE
SOCKET_ONERROR
SOCKET_ONMESSAGE
Each callback is passed the raw websocket event object
Update state in the open, close and error callbacks. You can also check the socket state directly with the this.$socket
object on the main Vue object.
Handle all the data in the SOCKET_ONMESSAGE
mutation.
Reconect events will commit mutations SOCKET_RECONNECT
and SOCKET_RECONNECT_ERROR
.
import Vue from 'vue'
import Vuex from 'vuex'
app.use(Vuex);
export default createStore({
state: {
socket: {
isConnected: false,
message: '',
reconnectError: false,
}
},
mutations:{
SOCKET_ONOPEN (state, event) {
Vue.prototype.$socket = event.currentTarget
state.socket.isConnected = true
},
SOCKET_ONCLOSE (state, event) {
state.socket.isConnected = false
},
SOCKET_ONERROR (state, event) {
console.error(state, event)
},
// default handler called for all methods
SOCKET_ONMESSAGE (state, message) {
state.socket.message = message
},
// mutations for reconnect methods
SOCKET_RECONNECT(state, count) {
console.info(state, count)
},
SOCKET_RECONNECT_ERROR(state) {
state.socket.reconnectError = true;
},
},
actions: {
sendMessage: function(context, message) {
.....
Vue.prototype.$socket.sendObj(message)
.....
}
}
})
// mutation-types.js
const SOCKET_ONOPEN = '✅ Socket connected!'
const SOCKET_ONCLOSE = '❌ Socket disconnected!'
const SOCKET_ONERROR = '❌ Socket Error!!!'
const SOCKET_ONMESSAGE = 'Websocket message received'
const SOCKET_RECONNECT = 'Websocket reconnected'
const SOCKET_RECONNECT_ERROR = 'Websocket is having issues reconnecting..'
export {
SOCKET_ONOPEN,
SOCKET_ONCLOSE,
SOCKET_ONERROR,
SOCKET_ONMESSAGE,
SOCKET_RECONNECT,
SOCKET_RECONNECT_ERROR
}
// store.js
import Vuex from 'vuex'
import {
SOCKET_ONOPEN,
SOCKET_ONCLOSE,
SOCKET_ONERROR,
SOCKET_ONMESSAGE,
SOCKET_RECONNECT,
SOCKET_RECONNECT_ERROR
} from './mutation-types'
app.use(Vuex);
export default createStore({
state: {
socket: {
isConnected: false,
message: '',
reconnectError: false,
}
},
mutations: {
[SOCKET_ONOPEN](state, event) {
state.socket.isConnected = true
},
[SOCKET_ONCLOSE](state, event) {
state.socket.isConnected = false
},
[SOCKET_ONERROR](state, event) {
console.error(state, event)
},
// default handler called for all methods
[SOCKET_ONMESSAGE](state, message) {
state.socket.message = message
},
// mutations for reconnect methods
[SOCKET_RECONNECT](state, count) {
console.info(state, count)
},
[SOCKET_RECONNECT_ERROR](state) {
state.socket.reconnectError = true;
}
}
})
// index.js
import store from './store'
import {
SOCKET_ONOPEN,
SOCKET_ONCLOSE,
SOCKET_ONERROR,
SOCKET_ONMESSAGE,
SOCKET_RECONNECT,
SOCKET_RECONNECT_ERROR
} from './mutation-types'
const mutations = {
SOCKET_ONOPEN,
SOCKET_ONCLOSE,
SOCKET_ONERROR,
SOCKET_ONMESSAGE,
SOCKET_RECONNECT,
SOCKET_RECONNECT_ERROR
}
app.use(VueNativeSock, 'ws://localhost:9090', {
store: store,
mutations: mutations
})
All data passed through the websocket is expected to be JSON.
Each message is JSON.parse
d if there is a data (content) response.
If there is no data, the fallback SOCKET_ON*
mutation is called with the original event data, as above.
If there is a .namespace
on the data, the message is sent to this namespaced: true
store (be sure to turn this on in the store module).
If there is a .mutation
value in the response data, the corresponding mutation is called with the name SOCKET_[mutation value]
If there is an .action
value in the response data ie. action: 'customerAdded'
, the corresponding action is called by name:
actions: {
customerAdded (context) {
console.log('action received: customerAdded')
}
}
Use the .sendObj({some: data})
method on the $socket
object to send stringified json messages.
Provide you own custom code to handle events received via the passToStoreHandler
option. The function you provide will be passed the following arguments:
- event name
- event
- original/default handler code function
function (eventName, event)
. This allows you to optionally do some basic preprocessing before handing the event over to the original handler.
The original passToStore code is used if no passToStoreHandler
is configured.
Here is an example of passing in a custom handler. This has the original passToStore code to give you an example of what you can do:
app.use(VueNativeSock, 'ws://localhost:9090', {
passToStoreHandler: function (eventName, event) {
if (!eventName.startsWith('SOCKET_')) { return }
let method = 'commit'
let target = eventName.toUpperCase()
let msg = event
if (this.format === 'json' && event.data) {
msg = JSON.parse(event.data)
if (msg.mutation) {
target = [msg.namespace || '', msg.mutation].filter((e) => !!e).join('/')
} else if (msg.action) {
method = 'dispatch'
target = [msg.namespace || '', msg.action].filter((e) => !!e).join('/')
}
}
this.store[method](target, msg)
}
})
Here is an example of do some preprocessing, then pass the event onto the original handler code:
app.use(VueNativeSock, 'ws://localhost:9090', {
passToStoreHandler: function (eventName, event, next) {
event.data = event.should_have_been_named_data
next(eventName, event)
}
})
TODO: post your example here!
Derived from https://github.com/MetinSeylan/Vue-Socket.io