mirror of
https://github.com/tenrok/vue-native-websocket.git
synced 2026-05-17 04:59:37 +03:00
8874a37abd
I guess it was a typo, changed `send` => `sendObj` in store's action.
346 lines
8.6 KiB
Markdown
Executable File
346 lines
8.6 KiB
Markdown
Executable File
# vue-native-websocket · [](https://travis-ci.org/nathantsoi/vue-native-websocket) [](https://www.npmjs.com/package/vue-native-websocket)
|
|
|
|
native websocket implementation for Vuejs 2 and Vuex
|
|
|
|
## Install
|
|
|
|
``` bash
|
|
yarn add vue-native-websocket
|
|
|
|
# or
|
|
|
|
npm install vue-native-websocket --save
|
|
```
|
|
|
|
## Usage
|
|
|
|
#### Configuration
|
|
|
|
Automatic socket connection from an URL string
|
|
|
|
``` js
|
|
import VueNativeSock from 'vue-native-websocket'
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090')
|
|
```
|
|
|
|
Enable Vuex integration, where `'./store'` is your local apps store:
|
|
|
|
``` js
|
|
import store from './store'
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090', { store: store })
|
|
```
|
|
|
|
Set sub-protocol, this is optional option and default is empty string.
|
|
|
|
``` js
|
|
import VueNativeSock from 'vue-native-websocket'
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090', { protocol: 'my-protocol' })
|
|
```
|
|
|
|
Optionally enable JSON message passing:
|
|
|
|
``` js
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090', { format: 'json' })
|
|
```
|
|
|
|
JSON message passing with a store:
|
|
|
|
``` js
|
|
import store from './store'
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090', { store: store, format: 'json' })
|
|
```
|
|
|
|
Enable ws reconnect automatically:
|
|
|
|
``` js
|
|
Vue.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:
|
|
|
|
``` js
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090', {
|
|
connectManually: true,
|
|
})
|
|
const vm = new Vue()
|
|
// 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()
|
|
```
|
|
|
|
#### On Vuejs instance usage
|
|
|
|
``` js
|
|
var vm = new Vue({
|
|
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'})
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
#### Dynamic socket event listeners
|
|
|
|
Create a new listener, for example:
|
|
|
|
``` js
|
|
this.$options.sockets.onmessage = (data) => console.log(data)
|
|
```
|
|
|
|
Remove existing listener
|
|
|
|
``` js
|
|
delete this.$options.sockets.onmessage
|
|
```
|
|
|
|
#### Vuex Store integration
|
|
|
|
Vuex integration works differently depending on if you've enabled a format
|
|
|
|
##### Without a format enabled
|
|
|
|
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`.
|
|
|
|
``` js
|
|
import Vue from 'vue'
|
|
import Vuex from 'vuex'
|
|
|
|
Vue.use(Vuex);
|
|
|
|
export default new Vuex.Store({
|
|
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)
|
|
.....
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
##### With custom mutation names
|
|
|
|
``` js
|
|
// 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 Vue from 'vue'
|
|
import Vuex from 'vuex'
|
|
import {
|
|
SOCKET_ONOPEN,
|
|
SOCKET_ONCLOSE,
|
|
SOCKET_ONERROR,
|
|
SOCKET_ONMESSAGE,
|
|
SOCKET_RECONNECT,
|
|
SOCKET_RECONNECT_ERROR
|
|
} from './mutation-types'
|
|
|
|
Vue.use(Vuex);
|
|
|
|
export default new Vuex.Store({
|
|
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
|
|
}
|
|
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090', {
|
|
store: store,
|
|
mutations: mutations
|
|
})
|
|
```
|
|
|
|
|
|
##### With `format: 'json'` enabled
|
|
|
|
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:
|
|
|
|
``` js
|
|
actions: {
|
|
customerAdded (context) {
|
|
console.log('action received: customerAdded')
|
|
}
|
|
}
|
|
```
|
|
|
|
Use the `.sendObj({some: data})` method on the `$socket` object to send stringified json messages.
|
|
|
|
##### Custom socket event handling
|
|
|
|
Provide you own custom code to handle events received via the `passToStoreHandler` option. The function you provide will be passed the following arguments:
|
|
|
|
1. event name
|
|
2. event
|
|
3. 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:
|
|
|
|
``` js
|
|
Vue.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:
|
|
|
|
``` js
|
|
Vue.use(VueNativeSock, 'ws://localhost:9090', {
|
|
passToStoreHandler: function (eventName, event, next) {
|
|
event.data = event.should_have_been_named_data
|
|
next(eventName, event)
|
|
}
|
|
})
|
|
```
|
|
|
|
## Examples
|
|
|
|
TODO: post your example here!
|
|
|
|
## Credits
|
|
|
|
Derived from https://github.com/MetinSeylan/Vue-Socket.io
|