vue-native-websocket-vue3 ·
仅支持vue3的websocket插件 | Only supports vue3 websocket plugin
English documents please move: README-EN.md
对Pinia进行兼容处理(感谢@chuck所提供的兼容代码)
插件安装
yarn add vue-native-websocket-vue3
npm install vue-native-websocket-vue3 --save
插件使用
如果你的项目启用了TypeScript,则在main.ts
文件中导入并使用插件。
没有启用就在main.js
中导入并使用。
使用插件时,第二个参数为必填项,是你的websocket
服务端连接地址。
import VueNativeSock from "vue-native-websocket-vue3";
app.use(VueNativeSock,"");
注意:插件依赖于Vuex,你的项目一定要安装vuex才可以使用本插件。vuex的相关配置请查阅文档后面的插件配置项中的内容。
同样的,插件也支持pinia,vuex与pinia任选其一即可。pinia的相关使用配置请请查阅文档后面的插件配置项中的内容。
插件配置项
插件提供了一些配置选项,提高了插件的灵活度,能更好的适配开发者的业务需求。
启用Vuex集成
在main.ts | main.js
中导入vuex
的配置文件,在使用插件时,第三个参数就是用户可以传配置项,他为一个对象类型,在对象中加入store
属性,值为导入的vuex。
import store from "./store";
app.use(VueNativeSock,"",{
store: store
});
如果你仍然不知道怎么用,可以去参考我的另一个开源项目chat-system。
如果启用了vuex集成,就需要在其配置文件中定义state以及mutations方法。mutations中定义的方法为websocket的6个监听,你可以在这几个监听中做相应的操作。
import { createStore } from "vuex";
import main from "../main";
export default createStore({
state: {
socket: {
isConnected: false,
message: "",
reconnectError: false,
heartBeatInterval: 50000,
heartBeatTimer: 0
}
},
mutations: {
SOCKET_ONOPEN(state, event) {
main.config.globalProperties.$socket = event.currentTarget;
state.socket.isConnected = true;
state.socket.heartBeatTimer = setInterval(() => {
const message = "心跳消息";
state.socket.isConnected &&
main.config.globalProperties.$socket.sendObj({
code: 200,
msg: message
});
}, state.socket.heartBeatInterval);
},
SOCKET_ONCLOSE(state, event) {
state.socket.isConnected = false;
clearInterval(state.socket.heartBeatTimer);
state.socket.heartBeatTimer = 0;
console.log("连接已断开: " + new Date());
console.log(event);
},
SOCKET_ONERROR(state, event) {
console.error(state, event);
},
SOCKET_ONMESSAGE(state, message) {
state.socket.message = message;
},
SOCKET_RECONNECT(state, count) {
console.info("消息系统重连中...", state, count);
},
SOCKET_RECONNECT_ERROR(state) {
state.socket.reconnectError = true;
}
},
modules: {}
});
自定义方法名
你也可以自定义mutations
中自定义websocket的默认监听事件名。
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
}
import { createStore } from "vuex";
import main from "../main";
import {
SOCKET_ONOPEN,
SOCKET_ONCLOSE,
SOCKET_ONERROR,
SOCKET_ONMESSAGE,
SOCKET_RECONNECT,
SOCKET_RECONNECT_ERROR
} from "./mutation-types"
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)
},
[SOCKET_ONMESSAGE](state, message) {
state.socket.message = message
},
[SOCKET_RECONNECT](state, count) {
console.info(state, count)
},
[SOCKET_RECONNECT_ERROR](state) {
state.socket.reconnectError = true;
}
},
modules: {}
});
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,"",{
store: store,
mutations: mutations
});
启用pinia集成
在main.js | main.ts
中导入pinia
的配置文件。
import { useSocketStoreWithOut } from './useSocketStore';
const store = useSocketStoreWithOut();
app.use(VueNativeSock, "", {
store: store
});
我专门写了一个demo用来演示pinia的集成,如果你需要参考的话请移步:pinia-websocket-project
pinia的socket配置文件代码如下:
import { defineStore } from 'pinia';
import { store } from '/@/store';
import main from '/@/main';
interface SocketStore {
isConnected: boolean;
message: string;
reconnectError: boolean;
heartBeatInterval: number;
heartBeatTimer: number;
}
export const useSocketStore = defineStore({
id: 'socket',
state: (): SocketStore => ({
isConnected: false,
message: '',
reconnectError: false,
heartBeatInterval: 50000,
heartBeatTimer: 0,
}),
actions: {
SOCKET_ONOPEN(event) {
main.config.globalProperties.$socket = event.currentTarget;
this.isConnected = true;
this.heartBeatTimer = window.setInterval(() => {
const message = '心跳消息';
this.isConnected &&
main.config.globalProperties.$socket.sendObj({
code: 200,
msg: message,
});
}, this.heartBeatInterval);
},
SOCKET_ONCLOSE(event) {
this.isConnected = false;
window.clearInterval(this.heartBeatTimer);
this.heartBeatTimer = 0;
console.log('连接已断开: ' + new Date());
console.log(event);
},
SOCKET_ONERROR(event) {
console.error(event);
},
SOCKET_ONMESSAGE(message) {
this.message = message;
},
SOCKET_RECONNECT(count) {
console.info('消息系统重连中...', count);
},
SOCKET_RECONNECT_ERROR() {
this.reconnectError = true;
},
},
});
export function useSocketStoreWithOut() {
return useSocketStore(store);
}
为了方便在组件外面使用pinia,这里额外导出了useSocketStoreWithOut
,否则pinia会报错,提示找不到pinia实例。
pinia的store配置代码如下:
import type { App } from 'vue';
import { createPinia } from 'pinia';
const store = createPinia();
export function setupStore(app: App<Element>) {
app.use(store);
}
export { store };
其它配置
下述方法,均为插件的可传参数,可以和store
搭配使用
{
"protocol": "my-protocol"
}
- 启用JSON消息传递,开启后数据发送与接收均采用json作为数据格式。
{
"format": "json"
}
如果你没启用JSON消息传递,只能使用send
方法来发送消息.
- 启用自动重连
reconnection
,启用时可配置重连次数reconnectionAttempts
与重连间隔时长reconnectionDelay
{
"reconnection": true,
"reconnectionAttempts": 5,
"reconnectionDelay": 3000
}
{
"connectManually": true
}
启用手动管理连接后,项目启动时则不会自动连接,你可以在项目的特定组件调用连接方法来进行连接。在组件销毁时调用关闭方法来关闭连接。
如果你启用了手动连接,必须要要启用vuex,否则此设置将不会生效。
this.$connect("");
this.$disconnect();
proxy.$connect("");
proxy.$disconnect("");
- 自定义socket事件处理
触发vuex里的mutations事件时,你可以选择自己写函数处理,做你想做的事情,在使用插件时传入
passToStoreHandler
参数即可,如果你没有传则走默认的处理函数,默认函数的定义如下:
export default class {
defaultPassToStore(
eventName: string,
event: {
data: string;
mutation: string;
namespace: string;
action: string;
}
): void {
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: string) => !!e).join("/");
} else if (msg.action) {
method = "dispatch";
target = [msg.namespace || "", msg.action].filter((e: string) => !!e).join("/");
}
}
if (this.mutations) {
target = this.mutations[target] || target;
}
if (this.store._p) {
target = eventName.toUpperCase();
this.store[target](msg);
} else {
this.store[method](target, msg);
}
}
}
当你要自定义一个函数时,这个函数接收3个参数:
- event name 事件名
- event 事件
- 默认事件处理,这使你可以选择将事件移交给原始处理程序之前进行一些基本的预处理
下面是一个例子
app.use(VueNativeSock, "", {
passToStoreHandler: function (eventName, event, next) {
event.data = event.should_have_been_named_data
next(eventName, event)
}
})
插件暴露的函数
send
发送非json类型的数据(使用插件时不能启用JSON消息传递)sendObj
发送json类型的数据(必须在使用插件时启用JSON消息传递)$connect
连接websocket服务器(必须在使用插件时启用手动管理连接选项)onmessage
收到服务端推送消息时的监听$disconnect
断开websocket连接
注意:上述方法均支持在optionsAPI与CompositionAPI中使用,具体的用法请查阅相关函数的文档。
在组件中使用
做完上述配置后,就可以在组件中使用了,如下所示为发送数据的例子。
export default defineComponent({
methods: {
clickButton: function(val) {
this.$socket.send('some data');
this.$socket.sendObj({ awesome: 'data'} );
}
}
})
注意:sendObj
方法必须在你启用JSON消息传递时才可以使用,不然只能使用send
方法。
消息监听,即接收websocket服务端推送的消息,如下所示为消息监听的示例代码。
this.$options.sockets.onmessage = (res: { data: string }) => {
console.log(data);
}
import { getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
proxy.$socket.onmessage = (res: {
data: string;
}) => {
console.log(data);
}
发送消息,向服务端推送消息
this.$socket.sendObj({msg: '消息内容'});
const internalInstance = data.currentInstance;
internalInstance?.proxy.$socket.sendObj({
msg: "消息内容"
});
compositionAPI写法由于在setup中无法拿到vue实例,因此需要在页面挂载后将实例存储到全局对象中,用的时候再将实例取出来。详细使用方法可以参考我的chat-system中的写法:InitData.ts#L91 、EventMonitoring.ts#L50 、SendMessage.ts#L73 、contact-list.vue#L620
移除消息监听
delete this.$options.sockets.onmessage
delete proxy.$socket.onmessage
写在最后
至此,插件的所有使用方法就介绍完了。
想进一步了解插件源码的请移步项目的GitHub仓库:vue-native-websocket-vue3
Vue2版本请移步原插件:vue-native-websocket