# websocket聊天模板
[uniapp版本点击这里](WebSocket聊天.md)
<br />
<br />
**vuex**
store/modules/chat.js
```JavaScript
import { Message } from 'element-ui'
/**
* 聊天
*/
const state = {
// 是否打开连接
isOpen: false,
// websocket
socket: null,
// 心跳间隔
timeout: 10000,
// 心跳事件
interval: null,
// 重连次数
connectNum: 0,
// ws token
token: '',
// 当前聊天场景
currentToUser: {
id: 1,
name: '',
avatar: '',
type: 's' // s=单聊, g群聊
},
// 我的信息
wsUserInfo: {
addr: '',
avatar: '',
driver: '',
fd: 0,
id: 0,
ip: '',
nickName: '未登录',
token: ''
},
// 消息处理回调
wsCallback: null
}
const mutations = {
/**
* 关闭连接
*/
wsClose(state) {
if (state.isOpen) {
state.isOpen = false
state.socket.close()
}
},
/**
* ws用户登录
*
* @param {string} jwt jwtToken
*/
wsLogin(state, jwt) {
this.dispatch('chat/SendRaw', {
call: 'login.token',
data: {
token: jwt
}
})
},
/**
* 设置ws收到消息回调
*
* @param {function} callback
*/
set_message_callback(state, callback) {
state.wsCallback = callback
},
/**
* 设置当前聊天对象
*
* @param {object} payload {to:对方id, type:'类型, s=单聊/g=群聊'}
*/
set_chat_object(state, payload) {
state.currentToUser.id = payload.id
state.currentToUser.type = payload.type
state.currentToUser.name = ''
state.currentToUser.avatar = ''
// 查询用户信息
this.dispatch('chat/SendRaw', {
call: 'user.get',
data: {
uid: payload.id
}
})
}
}
const actions = {
/**
* 初始化 or 连接websocket
*/
initWs({ commit, state, rootState }) {
const that = this
console.log('检查是否已链接')
if (state.isOpen) return // 防止重复连接
// 连接ws
const wsurl = process.env.VUE_APP_WEB_SOCKET
state.socket = new WebSocket(wsurl)
if (!state.socket) return // 连接失败
// 事件_连接成功
state.socket.onopen = () => {
console.log('ws连接成功')
// 将连接状态设为已连接
state.isOpen = true
// 心跳定时器
state.interval = setInterval(() => {
// 发送心跳
if (state.isOpen) {
try {
state.socket.send('ping')
} catch (err) {
console.log('心跳发送失败了 ...执行重连', err)
Message({
msg: '正在尝试重新连接' + (state.connectNum + 1) + '次',
type: 'error',
duration: 2 * 1000
})
state.isOpen = false
that.dispatch('chat/reConnect')
}
}
}, state.timeout)
}
// 事件_收到消息
state.socket.onmessage = (e) => {
// 服务器响应心跳
if (e.data === 'pong') { return }
// 解析包
const pack = JSON.parse(e.data)
if (typeof pack !== 'object') { return }
// 包拦截处理
switch (pack.call) {
case 'login.token': // 登录
state.token = pack.result.token
state.wsUserInfo = pack.result
break
case 'chat.recv': // 收到信息
// TODO: 播放提示音
break
case 'user.get': // 用户信息获取
// 更新聊天对象的用户信息
if (pack.result.id == state.currentToUser.id) {
state.currentToUser.name = pack.result.nickName
state.currentToUser.avatar = pack.result.avatar
}
break
}
// 转向回调处理
if (typeof state.wsCallback == 'function') {
state.wsCallback(pack)
}
}
// 事件_连接关闭
state.socket.onclose = () => {
state.isOpen = false
state.socket = null
// 清除定时器
clearTimeout(state.interval)
state.interval = null
}
// 事件_连接错误
state.socket.onerror = (e) => {
state.isOpen = false
state.socket = null
}
},
/**
* 重连
*/
reConnect({ commit, state }) {
// 逐渐延长重连时间
var time = 3000;
if (state.connectNum < 20) {
time = 3000;
} else if (state._connectNum < 50) {
time = 10000;
} else {
time = 450000;
}
state.timer = setTimeout(() => {
this.dispatch('chat/initWs')
}, time)
state.connectNum += 1
},
/**
* 发送消息
*
* @param {object} payload 消息数据
*
* payload格式:
* {type:消息类型, msg:消息数据}
*/
SendMsg({ commit, state }, payload) {
var data = {
to: payload.to,
origin: state.currentToUser.type,
type: payload.type,
msg: payload.msg
}
this.dispatch('chat/SendRaw', { call: 'chat.send', data: data })
},
/**
* 发送数据
*
* @param {object} data
*
* data格式:
* { call:"请求标识", data:{...其他数据...} }
*/
SendRaw({ commit, state }, data) {
try {
const message = {
call: data.call,
body: data.data,
token: state.token
}
const msgText = JSON.stringify(message)
console.log(typeof state.socket)
if (state.socket && state.isOpen) {
state.socket.send(msgText)
}
} catch (err) {
console.log(err)
}
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
```
**使用**
在vuex里引入模块
```JavaScript
const store = new Vuex.Store({
modules: {
chat // chat
},
getters
})
```
连接 (main.js)
```javascript
// 连接websocket
store.dispatch('chat/initWs')
```
登录
```JavaScript
store.commit('chat/wsLogin', state.token) // 在用户登录后, 同步登录ws
```
- 前言
- Android
- 签名证书生成
- JavaScript
- WebSocket 协议心跳
- 选择预览本地图片(不上传)
- Ajax 上传文件
- 代码片
- js 播放声音
- Verify 验证
- 验证金额 / 限制保留两位小数
- 原型链&继承
- 经典算法
- 冒泡排序
- 递归算法
- 二分查找
- 帮助函数
- 取URL查询参数为对象
- Date 日期时间
- 浅拷贝与深拷贝
- 进制转换
- Canvas
- 画圆形头像
- 计算字符串宽度
- 常用第三方包
- XLSX
- Layui
- layer.open select 遮挡问题
- 模板中使用 JS 表达式
- Form 表单
- on 监听事件
- select 下拉选择框
- 取表单数据 / 置表单数据
- form.verify 表单验证
- address 三级联动
- Table 表格
- 动态添加表格行
- 设置行高
- 单元格显示图片
- 开启编辑-阻止用户修改
- 主动触发事件
- 文件上传
- 单图上传
- Vue
- Vue.js 代码片
- 模态框/弹出层
- 单页面电影院选座
- vuex
- WebSocket聊天模板
- 解决办法
- vue-router多级路由中无父级组件设置方法
- Mui
- vue2+mui实现上拉刷新下拉加载
- JQuery
- 序列号表单为 JSON 对象
- Ajax 网络请求
- 选择器
- 插件
- selectpage
- HTML+CSS 布局
- Nodejs
- flex 布局
- 水平对齐方式
- 垂直对齐方式
- 九宫格/列表
- PHP
- gd 图像处理
- 图片写字
- 图片合并
- 图像压缩
- 图片写字居中
- 超全局变量
- helper 帮助函数
- ThinkPHP
- 生成用户分享二维码
- tp5.0 模型关联查询field无效
- Composer
- phpmailer
- 第三方接口
- 快递 100 物流记录
- 动态加载
- pdf解决方案
- 图片转换pdf
- 阿里云
- OSS 对象储存
- 阿里短信
- 辅助函数
- 取两个数组差异部分
- 从完整地址中取出省市区
- 钉钉
- 进制转换 & pack/unpack
- Yii2
- ActiveForm 常见问题
- FastAdmin
- layer的妙用
- \fast\Auth 权限
- 前端的各种常见问题
- 点击图片放大预览
- js
- ajax请求
- 前端
- Table
- selectPage
- 后端
- 腾讯cos插件后台上传文件工具类
- XDebug
- php.ini
- Linux
- RabbitMQ
- 防火墙
- iptables
- firewalld
- 环境变量
- shell
- bash
- crontab 定时任务
- 数据归档与解压缩
- tar
- 图像处理
- imagemagick
- 文档表格处理
- 转换word、pdf等
- 常用命令
- 文件资源管理
- xxd 十六进制编辑与查看
- 疑难杂症
- 开启swap虚拟文件系统缓解内存紧张卡顿
- wine
- deepin-wine(qq/微信综合)
- Python
- 代码片
- bs4 解析 html 插入到数据库
- webdriver 操作浏览器
- requests 请求库
- easyxlsx 导出 excel
- opencv
- 提取印章
- orc图片文字识别
- tesseract
- 进制转换
- WebSocket
- ws 服务示例
- 进程守护
- PM2
- Golang
- net/http
- Server
- 基本
- array 数组
- 循环
- os 文件目录基本操作
- map
- json处理
- Qrcode 二维码
- go-sqlite3
- go-redis
- mysql
- go-sql-driver
- 正则表达式
- beego
- fmt
- io
- ioutil
- net
- http
- Docker
- docker run
- Nginx
- CORS 允许跨域配置
- 负载均衡&反向代理
- rewaite 重写
- nginx配置
- 易语言
- 汇编 call 执行子程序
- HpSocketTcp 大文件传输
- 类指针
- Vim
- UniApp
- request.js
- 微信小程序登录处理(oauth2)
- vuex
- WebSocket聊天
- 腾讯云-人脸核身
- Java
- Spring Boot
- 请求与响应
- nginx部署
- 配置文件
- 创建项目
- 控制器
- 一个控制器示例
- 数据库
- MySQL
- 集成 SLF4J
- 集成 PageHelper 分页
- maven
- Markdown
- mermaid
- ffmpeg
- 基本使用
- 介绍/安装
- 简单示例
- php
- python
- office
- excel
- 单元格选择数据区域
- 截取字符串
- vlookup 选择值
- iferror 错误默认值
- search 搜索
- weekday 取星期几
- left 取左边n个字符
- right 取右边n个字符
- sum 合计
- sumif 条件合计
- sumifs 多条件合计
- datedif 取时间间隔
- roundup 向上舍入数字
- rounddown 向下舍入数字
- large 取第n大值
- mod 求余函数
- word
- 邮件合并-保留两位小数
- MySql
- 安装
- 基础操作
- 备份还原数据库
- 创建、删除、修改数据表
- 表结构查询
- Docker方案
- 慢查询
- 全文搜索
- 备份与还原
- 备份数据表
- 支付
- 支付宝
- ssh证书生成
- 支付申请
- 成考
- 英语
- 音标-掐头法
- 音标-去尾法
- 音标-元音
- 对比法学习辅音发音
- 短元音-长元音
- 双元音
- 数学
- 1.实数系
- 2.乘方
- 3.代数式
- 4.单项式多项式
- 5.整式的概念与方程综合
- 6.合并同类项和移项
- 7.二次根式
- 8.方程
- Git
- WebHook
- 宝塔
- webhook工具实现
- commit 规范
- 安装
- 创建
- 发布、提交
- 查看
- 更新
- 分支
- 找回文件、目录
- Svn
- 设置默认编辑器
- ignore 忽略提交目录
- revert 恢复撤销
- C语言
- 环境安装
- 基础部分
- 单片机
- ESP8266
- ESP8266开发环境安装
- 基础知识
- sim800
- Windows
- Win7
- Win10
- wsl (Linux子系统)
- ArtTemplate
- 正则表达式
- 常用正则
- VsCode
- easy less
- 腾讯云
- 数据万象
- 任务接口
- 音视频转码任务
- 算法
- 宽高按比例缩放大小尺寸
- IOS
- 开发者账号
- uniapp-ios打包上架的坑
- 协议模板
- 隐私协议
- 酸酸乳
- bower
- SQL Server
- 多行数据连接字符串
- GROUP BY选取其他字段
- 支付宝
- IoT小程序
- 支付
- RSA秘钥生成