1、创建一个store文件夹,并在其中创建store.js文件:在store,js文件夹中引入vuex,并创建vuex实例,无需在main.js中引用vuex,在main,js中全局挂载store

import Vue from 'vue'
import Vuex from 'vuex'   
import common from "../common/common.js";
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
/**
* 是否需要强制登录
*/
forcedLogin: false,
hasLogin: false,
userName: "",
carData:[],
finishedProductData:[],
account:'',
socketTask: null,
websocketData:{},
initConnect:false,//初始化连接状态
lockReconnect:true,
timeout: 5 * 1000, //每5秒发起一次心跳,
timeoutObj: null, //⼼跳⼼跳倒计时
dispatchHeartObj:null,
showReconnect:false ,//正在重连,
heartTimeNum:0,
},
mutations: {
login(state, userName) {
state.userName = userName || '新用户';
state.hasLogin = true;
},
logout(state) {
state.userName = "";
state.hasLogin = false;
},
setCarData(state,info){
state.carData=info
},
setFinishedProductData(state,info){
state.finishedProductData=info
},
setAccount(state,info){
state.account=info
},
setWebsocketData (state, data) {
state.websocketData = data
// console.log(state.websocketData)
}
},

//actions存放异步函数
actions: {
//websocket初始化
websocketInit ({ state, dispatch }, url) { //actions的函数有两个:context和value,其中context包括state,dispatch,commit等,这里使用了解构的方式
state.socketTask = uni.connectSocket({
url, // url是websocket连接ip
success: () => {
console.log('成功')
},
fail: e => {
state.lockReconnect=false
}
})

//websocket自带的监听函数:onOpen,onMessage,onClose,onError
state.socketTask.onOpen(() => dispatch('websocketOnOpen'))  //websocketOnOpen是异步函数且写在actions函数内部,所以要使用dispatch关键字来触发
state.socketTask.onMessage(res => dispatch('websocketOnMessage', res))
state.socketTask.onClose(e => dispatch('websocketOnClose',e))
state.socketTask.onError(e => dispatch('websocketOnError',e))
//在初始化时触发心跳,重连时不可再调用,否则会产生多个setInterval定时器,使心跳无法保证每5秒执行一次
if(state.dispatchHeartObj!=null){
clearTimeout(state.dispatchHeartObj)
}
state.dispatchHeartObj=setTimeout(()=>{
dispatch('startWsHeartbeat')
},1000)
},
//重连调用
websocketconnect({state,dispatch},url){
state.socketTask = uni.connectSocket({
url, // url是websocket连接ip
success: () => {
},
fail: e => {
}
})
state.socketTask.onOpen(() => dispatch('websocketOnOpen'))
state.socketTask.onMessage(res => dispatch('websocketOnMessage', res))
state.socketTask.onClose(e => dispatch('websocketOnClose',e))
state.socketTask.onError(e => dispatch('websocketOnError',e))
},
websocketOnOpen () {
},
// 收到数据,此处无需进行心跳重置
websocketOnMessage ({ commit,dispatch,state}, res) {
if(res){
state.lockReconnect=true
state.showReconnect=false
state.heartTimeNum=0
if (res.data !== '连接成功') {
commit('setWebsocketData', (JSON.stringify(res)))
}
}
},
//websocket关闭监听
websocketOnClose ({ state,commit, dispatch },e) {
state.initConnect=false //可以在这里修改state变量,但不推荐,一般使用commit来触发
},
websocketOnError ({ commit, dispatch,state },e) {
state.lockReconnect = false;
state.initConnect=false
},
//手动关闭
websocketClose ({ state,dispatch }) {
if (state.socketTask==null){
return
}
state.socketTask.close({
success (res) {
state.lockReconnect = false;
dispatch('reconnect')
},
fail (err) {
}
})
},
// 手动发送数据
websocketSend ({ state }, data) {
uni.sendSocketMessage({
data,
success: res => {
},
fail: e => {
}
})
},
//开启心跳
startWsHeartbeat({ state,dispatch}, data) {
if(state.timeoutObj!=null){
clearInterval(state.timeoutObj)
}
//每5秒发送一次心跳请求
state.timeoutObj=setInterval(() => {
var sendData={
Command:'0004',
Ip:common.apiUrllogo,
SerialNumber:Math.random(),
Status:'2',
Result:'前端发起心跳请求'
}
dispatch('websocketSend',JSON.stringify(sendData))
//心跳次数递增
state.heartTimeNum++
//规定30秒之内如果接收不到服务端的心跳反馈,就手动关闭websocket,以便重连
if(state.heartTimeNum*5000>30*1000){
dispatch('websocketClose')
state.lockReconnect = false;
}
},5000)

},
//重连
reconnect({ state,dispatch}) {
if(state.lockReconnect==true){
return;
};
state.showReconnect=true
dispatch('websocketconnect',"ws://" + common.apiUrllogo + "/webSocket")
},
}
})

export default store

2、在main.js文件中全局挂载store

import store from './store/store.js'

Vue.prototype.$store = store;

const app = new Vue({
store,//挂载,
...App
})

3、在外部文件使用store:

methods: {
createWebsocket(){
if(this.$store.state.initConnect==false){
this.$store.dispatch('websocketInit', "ws://" + common.apiUrllogo + "/webSocket") //$store为全局挂载的变量,使用dispatch关键字调用store.js文件中的actions函数中的websocketInit方法
this.$store.state.initConnect=true   //使用.$store.state.变量来修改state变量
}
},

}