uniapp项目实践总结(十五)使用websocket实现简易聊天室
导语:在一些社交软件中,经常可以看到各种聊天室的界面,接下来就总结一下聊天室的原理个实现方法,最后做一个简易的聊天室,包括登录/登出、加入/离开房间、发送接收聊天消息等功能。
目录
- 准备工作
- 原理分析
- 组件实现
- 实战演练
- 服务端搭建
- 案例展示
准备工作
- 在
pages/index
文件夹下面新建一个名叫chat
的组件; - 按照前一篇所说的页面结构,编写好预定的聊天页面;
原理分析
前端部分
此聊天室前端方面使用了 uniapp 提供的几个 API 实现包括:
uni.connectSocket
:连接到 websocket 服务器;SocketTask.onOpen
:监听服务端连接打开;SocketTask.onClose
:监听服务端连接关闭;SocketTask.onError
:监听服务端连接错误;SocketTask.onMessage
:监听服务端的消息;SocketTask.send
:向服务端发送消息;SocketTask.close
:关闭服务端连接;
后端部分
此聊天室服务端使用 npm 库ws
搭建,另外头像上传部分使用原生node
实现,待会儿会详细介绍实现方法。
组件实现
准备工作和原理分析完成后,接下来写一个简单的页面,下面主要是展示主要的内容。
模板部分
- 登录部分
包括输入用户名和上传头像的页面和功能。
<view class="chat-login" v-if="!wsInfo.isLogin"><view class="chat-login-item"><inputv-model="userInfo.name"class="chat-login-ipt"type="text":maxlength="10"placeholder="请输入用户名" /></view><view class="chat-login-item"><button class="chat-login-ipt" @click="uploadAvatar">上传头像</button></view><view class="chat-login-item"><button class="chat-login-btn" type="primary" @click="wsLogin">用户登录</button></view>
</view>
- 加入房间部分
包括选择房间的退出登录的页面和功能。
<view class="chat-login" v-if="wsInfo.isLogin && !wsInfo.isJoin"><view class="chat-login-item"><picker mode="selector" :range="roomInfo.list" :value="roomInfo.id" @change="changeRoom">请选择房间号:{{roomInfo.name}}</picker></view><view class="chat-login-item"><button class="chat-login-btn" type="primary" @click="joinRoom">进入房间</button></view><view class="chat-login-item"><button type="warn" @click="wsLogout">退出登录</button></view>
</view>
- 聊天室界面
包括展示房间号,退出房间,在线用户列表,聊天消息区域以及输入聊天内容和发送消息的页面和功能。
<view class="chat-room" v-if="wsInfo.isLogin && wsInfo.isJoin"><view class="chat-room-set"><text class="chat-room-name">房间{{ roomInfo.id }}</text><button class="chat-room-logout" size="mini" type="warn" @click="leaveRoom">退出房间</button></view><view class="chat-room-users">在线人数({{userInfo.users.length}}人):{{ userInfo.usersText }}</view><scroll-view:scroll-y="true":scroll-top="roomInfo.scrollTop"@scroll="handlerScroll"class="chat-room-area"><view:class="{'chat-room-area-item': true, 'active': item.name == userInfo.name}"v-for="(item, index) in msg.list":key="`msg${index+1}`"><view class="chat-room-user"><textv-if="roomInfo.mode == 'name'":class="{'chat-room-username': true, 'active': item.name == userInfo.name}">{{ item.name }}</text><text v-if="roomInfo.mode == 'name'" class="chat-room-time"> ({{item.createTime}}): </text></view><imagev-if="roomInfo.mode == 'avatar'"class="chat-room-avatar":src="item.name == userInfo.name ? userInfo.avatar : item.avatar"></image><view class="chat-room-content"> {{item.content}} </view></view><view id="chat-room-area-pos"></view></scroll-view><view class="chat-room-bot"><inputclass="chat-room-bot-ipt"type="text"placeholder="请输入内容":maxlength="100"v-model="msg.current" /><button class="chat-room-bot-btn" size="mini" type="primary" @click="sendMsg">发送</button></view>
</view>
样式部分
- 登录和加入房间样式
.chat-login {.chat-login-item {margin-bottom: 20rpx;height: 80rpx;.chat-login-ipt,uni-picker {box-sizing: border-box;padding: 10rpx 30rpx;height: 100%;font-size: 26rpx;border: 1rpx solid $e;border-radius: 10rpx;color: var(--UI-BG-4);}uni-picker {display: flex;align-items: center;}.chat-login-btn {background: $mainColor;}}
}
- 聊天房间页面样式
.chat-room {display: flex;flex-direction: column;height: 100%;.chat-room-set {display: flex;justify-content: space-between;align-items: center;width: 100%;font-size: 31rpx;font-weight: bold;.chat-room-name {padding: 10rpx;}.chat-room-logout {margin: 0;}}.chat-room-users {margin: 20rpx 0;padding: 20rpx 0;font-size: 28rpx;line-height: 1.5;border-bottom: 2rpx solid $e;word-break: break-all;}.chat-room-area {box-sizing: border-box;padding: 20rpx;height: calc(100% - 280rpx);background: $f8;.chat-room-area-item {display: flex;flex-direction: row;justify-content: flex-start;align-items: flex-start;margin-bottom: 20rpx;padding-bottom: 20rpx;.chat-room-user {.chat-room-username {color: $iptBorColor;font-size: 31rpx;line-height: 2;&.active {color: $mainColor;}}}.chat-room-avatar {width: 68rpx;height: 68rpx;background: $white;border-radius: 10rpx;}.chat-room-time {font-size: 26rpx;color: $iptBorColor;}.chat-room-content {box-sizing: border-box;margin-left: 12rpx;padding: 15rpx;max-width: calc(100% - 80rpx);text-align: left;font-size: 24rpx;color: $white;border-radius: 10rpx;word-break: break-all;background: $mainColor;}&.active {flex-direction: row-reverse;.chat-room-content {margin-left: 0;margin-right: 12rpx;text-align: right;color: $uni-text-color;background: $white;}}}}.chat-room-bot {position: fixed;bottom: 0;left: 0;display: flex;justify-content: space-between;align-items: center;box-sizing: border-box;padding: 0 30rpx;width: 100%;height: 100rpx;background: $white;border-top: 3rpx solid $f8;.chat-room-bot-ipt {flex: 1;box-sizing: border-box;padding: 0 30rpx;height: 70rpx;font-size: 24rpx;border: 2rpx solid $iptBorColor;border-radius: 10rpx;}.chat-room-bot-btn {margin-left: 50rpx;width: 150rpx;height: 70rpx;line-height: 70rpx;font-size: 26rpx;color: $white;background: $mainColor;}}
}
脚本部分
引入依赖包和属性设置
- websocket 信息
// ws
let wsInfo = reactive({ws: null, // ws对象alive: false, // 是否连接isLogin: false, // 是否登录isJoin: false, // 是否加入lock: false, // 锁住重连reconnectTimer: null, // 重连计时reconnectTime: 5000, // 重连计时间隔clientTimer: null, // 客户端计时clientTime: 10000, // 客户端计时间隔serverTimer: null, // 服务端计时serverTime: 30000, // 服务端计时间隔
});
- 用户信息
// 用户信息
const userInfo = reactive({id: "1", // 用户idname: "", // 用户名称avatar: "", // 用户头像users: [], // 用户在线列表usersText: "", // 用户在线列表文本
});
- 房间信息
// 房间信息
const roomInfo = reactive({id: 1, // 房间idname: "房间1", // 房间名称list: ["房间1", "房间2", "房间3"], // 房间列表mode: "avatar", // 模式:avatar头像scrollTop: 0, // 滚动到顶部距离scrollHei: 0, // 滚动高度goBottomTimer: null, // 到底部计时goBottomTime: 500, // 到顶部计时间隔
});
- 聊天信息
// 聊天信息
const msg = reactive({current: "", // 输入框内容list: [], // 聊天消息列表
});
实战演练
基本工作准备完毕后,接下来就开始实现功能。
连接 websocket
进入页面后,首先连接上 websocket 服务端。
- 连接 websocket
// 连接ws
function connectWs() {wsInfo.ws = null;wsInfo.ws = uni.connectSocket({url: proxy.$apis.urls.wsUrl,success() {wsInfo.alive = true;console.log("ws连接成功!");},fail()
相关文章:
uniapp项目实践总结(十五)使用websocket实现简易聊天室
导语:在一些社交软件中,经常可以看到各种聊天室的界面,接下来就总结一下聊天室的原理个实现方法,最后做一个简易的聊天室,包括登录/登出、加入/离开房间、发送接收聊天消息等功能。 目录 准备工作原理分析组件实现实战演练服务端搭建案例展示准备工作 在pages/index文件夹…...

论文阅读之Learning and Generalization of Motor Skills by Learning from Demonstration
论文阅读其实就是用自己的话讲一遍,然后理解其中的方法 0、论文基本信息 为什么阅读此篇论文:因为它是DMP经典论文,被引多次,学史可以明智,了解最初机理。 论文题目:Learning and Generalization of Moto…...
SpringCloud中的Eureka的集群配置
微服务框架中最为重要的就是注册中心,如果只是单注册中心,一旦出现问题,容易导致整个微服务环境不可用,所以建议注册中心集群。 目前SpringCloud框架中使用Eureka作为注册中心,本文简单介绍一下Eureka的集群配置&…...

10 Ubuntu下配置STMCubeMX与CLion IDE联合环境搭建(不包含下载CLion的教程)
序言 果然作为一名测控系的学生,纯搞视觉多少还是有点与专业脱节,决定入坑嵌入式。选择STM32进行入门,并且使用CubeMX加CLion作为我的第一个真正意义上的嵌入式开发环境(大一的时候玩过一段时间,但是没什么技术&#…...

负载均衡原理及应用
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

视频讲解|1033含sop的配电网重构(含风光可多时段拓展)
目录 1 主要内容 程序特点 讲解重点 2 视频链接 1 主要内容 该视频为含sop的配电网重构matlab代码讲解,对应资源下载链接为含sop的配电网重构(含风光|可多时段拓展),程序主要内容是:针对含sop的配电网重构模型&…...
uni-app监听页面滚动
在uni-app中可以通过监听页面滚动事件来实现滚动效果或响应滚动事件 在需要监听滚动的页面或组件中,添加一个scroll元素,用于容纳内容并实现滚动效果。 <template><view class"container"><scroll-view scroll-y scroll"…...

[字符串和内存函数]strcmp字符串函数的详解和模拟
strcmp函数 strcmp函数是一个用于比较两个字符串的C标准库函数。它的原型为: int strcmp(const char* str1, const char* str2);strcmp函数会比较str1和str2两个字符串的字符序列,并返回一个整数值来表示它们之间的大小关系。返回值的含义如下ÿ…...
zookeeper 常见问题处理
调整jvm参数 [rootvm-02 conf]# cat /opt/app/zookeeper-3.4.14/bin/zkEnv.sh |grep java.env -A3 -B3ZOOCFG"$ZOOCFGDIR/$ZOOCFG"if [ -f "$ZOOCFGDIR/java.env" ] then. "$ZOOCFGDIR/java.env" fiif [ "x${ZOO_LOG_DIR}" "x&…...
repo 命令
repo命令是Google开发的用于管理Android版本库的一个工具。 repo命令并不是用于取代git,而是用Python对git进行了一定的封装,简化了对多个Git版本库的管理。 repo init -u -b -m <manifest 文件名称> repo sync 相当于 git clone 获取 git remote…...

一、 计算机网络概论
一、计算机网络概论 1、计算机网络概述 1.1、概念 计算机网络是一个将分散的、具有独立功能的计算机系统,通过通信设备与线路连接起来,由功能完善的软件实现资源共享和信息传递的系统 是一些互连的、自治的计算机系统的集合 以能够相互共享资源的方…...

从零学习开发一个RISC-V操作系统(一)丨计算机组成原理相关知识与RISC-V指令集简介
本篇文章的内容 一、计算机组成原理的相关知识1.1 计算机的硬件组成1.2 程序的存储与执行1.3 程序语言的设计和进化1.4 存储设备的层次结构1.5 操作系统 二、RISC-V的指令集ISA简介2.1 什么是ISA2.2 复杂指令集(CISC)和精简指令集(RISC&#…...

C++ - 异常介绍和使用
前言 我们在日常编写代码的时候,难免会出现编写错误带来程序的奔溃,或者是用户在使用我们编写的程序时候,使用错误所带来程序的奔溃。 在C 当中 可以对你觉得可能发生 错误 的地方在运行之前进行判断,发生错误可以给出提示。 C…...

iText实战--在现有PDF上工作
6.1 使用PdfReader读取PDF 检索文档和页面信息 D:/data/iText/inAction/chapter03/image_direct.pdf Number of pages: 1 Size of page 1: [0.0,0.0,283.0,416.0] Rotation of page 1: 0 Page size with rotation of page 1: Rectangle: 283.0x416.0 (rot: 0 degrees) Is reb…...

SQL优化--count优化
select count(*) from tb_user ;在之前的测试中,我们发现,如果数据量很大,在执行count操作时,是非常耗时的。 MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个 数,效率很…...

IDEA下使用Spring MVC
<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://ma…...
2022基金从业人员资格管理及后续职业培训 部分答案(自答)
2022基金从业人员资格管理及后续职业培训 区块链在金融交易后处理中的应用私募基金行业典型违法案例分析《证券法》修订情况报告《刑法修正案(十一)》金融犯罪条款中国结算港股通结算业务介绍商品投资与商品配置价值气候技术:实现双碳目标的技…...

阿里云通义千问向全社会开放,近期将开源更大参数规模大模型
9月13日,阿里云宣布通义千问大模型已首批通过备案,并正式向公众开放,广大用户可登录通义千问官网体验,企业用户可以通过阿里云调用通义千问API。 通义千问在技术创新和行业应用上均位居大模型行业前列。IDC最新的AI大模型评估报告…...
数据结构:二叉查找树
文章目录 二叉查找树一,概述二,添加数据三,删除数据 二叉查找树 一,概述 二叉查找树,也称为二叉搜索树,是一种特殊的二叉树,它或者是一颗空树,或者具有以下性质:对于每…...

Redis的介绍,安装Redis的方式
🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaEE 操作系统 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 Redis 初识Redis1.1 认识Redis1.2 安装Redis的方式…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...