当前位置: 首页 > news >正文

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

论文阅读其实就是用自己的话讲一遍&#xff0c;然后理解其中的方法 0、论文基本信息 为什么阅读此篇论文&#xff1a;因为它是DMP经典论文&#xff0c;被引多次&#xff0c;学史可以明智&#xff0c;了解最初机理。 论文题目&#xff1a;Learning and Generalization of Moto…...

SpringCloud中的Eureka的集群配置

微服务框架中最为重要的就是注册中心&#xff0c;如果只是单注册中心&#xff0c;一旦出现问题&#xff0c;容易导致整个微服务环境不可用&#xff0c;所以建议注册中心集群。 目前SpringCloud框架中使用Eureka作为注册中心&#xff0c;本文简单介绍一下Eureka的集群配置&…...

10 Ubuntu下配置STMCubeMX与CLion IDE联合环境搭建(不包含下载CLion的教程)

序言 果然作为一名测控系的学生&#xff0c;纯搞视觉多少还是有点与专业脱节&#xff0c;决定入坑嵌入式。选择STM32进行入门&#xff0c;并且使用CubeMX加CLion作为我的第一个真正意义上的嵌入式开发环境&#xff08;大一的时候玩过一段时间&#xff0c;但是没什么技术&#…...

负载均衡原理及应用

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

视频讲解|1033含sop的配电网重构(含风光可多时段拓展)

目录 1 主要内容 程序特点 讲解重点 2 视频链接 1 主要内容 该视频为含sop的配电网重构matlab代码讲解&#xff0c;对应资源下载链接为含sop的配电网重构&#xff08;含风光|可多时段拓展&#xff09;&#xff0c;程序主要内容是&#xff1a;针对含sop的配电网重构模型&…...

uni-app监听页面滚动

在uni-app中可以通过监听页面滚动事件来实现滚动效果或响应滚动事件 在需要监听滚动的页面或组件中&#xff0c;添加一个scroll元素&#xff0c;用于容纳内容并实现滚动效果。 <template><view class"container"><scroll-view scroll-y scroll"…...

[字符串和内存函数]strcmp字符串函数的详解和模拟

strcmp函数 strcmp函数是一个用于比较两个字符串的C标准库函数。它的原型为&#xff1a; int strcmp(const char* str1, const char* str2);strcmp函数会比较str1和str2两个字符串的字符序列&#xff0c;并返回一个整数值来表示它们之间的大小关系。返回值的含义如下&#xff…...

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&#xff0c;而是用Python对git进行了一定的封装&#xff0c;简化了对多个Git版本库的管理。 repo init -u -b -m <manifest 文件名称> repo sync 相当于 git clone 获取 git remote…...

一、 计算机网络概论

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

从零学习开发一个RISC-V操作系统(一)丨计算机组成原理相关知识与RISC-V指令集简介

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

C++ - 异常介绍和使用

前言 我们在日常编写代码的时候&#xff0c;难免会出现编写错误带来程序的奔溃&#xff0c;或者是用户在使用我们编写的程序时候&#xff0c;使用错误所带来程序的奔溃。 在C 当中 可以对你觉得可能发生 错误 的地方在运行之前进行判断&#xff0c;发生错误可以给出提示。 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 ;在之前的测试中&#xff0c;我们发现&#xff0c;如果数据量很大&#xff0c;在执行count操作时&#xff0c;是非常耗时的。 MyISAM 引擎把一个表的总行数存在了磁盘上&#xff0c;因此执行 count(*) 的时候会直接返回这个 数&#xff0c;效率很…...

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基金从业人员资格管理及后续职业培训 区块链在金融交易后处理中的应用私募基金行业典型违法案例分析《证券法》修订情况报告《刑法修正案&#xff08;十一&#xff09;》金融犯罪条款中国结算港股通结算业务介绍商品投资与商品配置价值气候技术&#xff1a;实现双碳目标的技…...

阿里云通义千问向全社会开放,近期将开源更大参数规模大模型

9月13日&#xff0c;阿里云宣布通义千问大模型已首批通过备案&#xff0c;并正式向公众开放&#xff0c;广大用户可登录通义千问官网体验&#xff0c;企业用户可以通过阿里云调用通义千问API。 通义千问在技术创新和行业应用上均位居大模型行业前列。IDC最新的AI大模型评估报告…...

数据结构:二叉查找树

文章目录 二叉查找树一&#xff0c;概述二&#xff0c;添加数据三&#xff0c;删除数据 二叉查找树 一&#xff0c;概述 二叉查找树&#xff0c;也称为二叉搜索树&#xff0c;是一种特殊的二叉树&#xff0c;它或者是一颗空树&#xff0c;或者具有以下性质&#xff1a;对于每…...

Redis的介绍,安装Redis的方式

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 Redis 初识Redis1.1 认识Redis1.2 安装Redis的方式…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...