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() 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80492.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【微信小程序】网络请求

环境&#xff1a;微信小程序开发工具 测试api&#xff08;随机获取猫咪靓照&#xff09;:https://api.thecatapi.com/v1/images/search?limit2 示例&#xff1a; 完整代码 request.wxml <button bind:tap"requestBtn" type"primary">网络请求&l…

javascript获取元素在浏览器中工作区域的左、右、上、下距离,或带滚动条的元素在页面中的大小

//获取元素在包含元素框中的大小 //第1个函数为获取元素在包含元素中左内边框的距离 function getELementLeft(element){//获取元素在包含元素左边距离var actualeftelement.offsetLeft;//获取元素的上级包含元素var currentelement.offsetParent;//循环到一直没有包含元素whil…

Otter改造 增加springboot模块和HTTP调用功能

环境搭建 & 打包 环境搭建&#xff1a; 进入 $otter_home/lib 目录执行&#xff1a;bash install.sh 打包&#xff1a; 进入$otter_home目录执行&#xff1a;mvn clean install -Dmaven.test.skip -Denvrelease发布包位置&#xff1a;$otter_home/target 项目背景 阿里…

【小沐学CAD】嵌入式UI开发工具:GL Studio

文章目录 1、简介2、软件功能3、应用行业3.1 航空3.2 汽车3.3 防御3.4 工业3.5 电力与能源3.6 医疗3.7 空间3.8 科技 结语 1、简介 https://disti.com/gl-studio/ DiSTI 是 HMI 软件、虚拟驾驶舱、仪表、信息娱乐、集群显示器和嵌入式 UI 解决方案的领先提供商。 而它的GL Stu…

React如何实现国际化?

目录 一、Redux准备工作 commonTypes.js commonActions.js commonReducer.js rootReducer.js 二、然后定义SelectLang组件 index.js index.less 三、创建语言包 welcomeLocale.js index.js 四、使用 react的入口文件 App.js welcome.js 附 关于如何实现国际…

OpenCV项目实战(2)— 如何用OpenCV实现弹球动画

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。OpenCV能够在画布上绘制静态的图形&#xff0c;例如&#xff0c;线段、矩形、正方形、圆形、多边形、文字等。那么&#xff0c;能不能让这些静态的图形移动起来&#xff1f;如果能&#xff0c;又该如何编写代码呢&#xff…

论文总结《A Closer Look at Few-shot Classification Again》

原文链接 A Closer Look at Few-shot Classification Again 摘要 这篇文章主要探讨了在少样本图像分类问题中&#xff0c;training algorithm 和 adaptation algorithm的相关性问题。给出了training algorithm和adaptation algorithm是完全不想关的&#xff0c;这意味着我们…

Day46:项目-购物车案例

购物车案例 准备工作 首页默认加载&#xff0c;其余页面懒加载 调用defineStore方法构建store 入口main做对应配置&#xff0c;找指南&#xff0c;快速开始&#xff0c;把elementplus引入进来 import { createApp } from "vue"; import { createPinia } from &qu…

典型数据结构-栈/队列/链表、哈希查找、二叉树(BT)、线索二叉树、二叉排序树(BST树)、平衡二叉树(AVL树)、红黑树(RB树)

目录 典型数据结构列举 栈/队列/链表 树 二叉树 线索二叉树 二叉排序树 平衡二叉树&#xff08;AVL树&#xff09; 红黑树 其它树种和应用介绍 典型数据结构列举 栈/队列/链表 描述略。 一些基本的简单实现参考/数据结构简单实现/文件夹里面。 线性表详解&#xff…

Spring Boot 动态加载jar文件

Spring Boot 动态加载jar文件 接口实现&#xff1a; package org.bc.device;public interface IDeviceHandler {String start();String stop(); }实现类&#xff1a; package org.bc.device; public class MqttDevice implements IDeviceHandler{ Override public String s…

【深度学习】Pytorch 系列教程(十):PyTorch数据结构:2、张量操作(Tensor Operations):(4)索引和切片详解

目录 一、前言 二、实验环境 三、PyTorch数据结构 0、分类 1、张量&#xff08;Tensor&#xff09; 2、张量操作&#xff08;Tensor Operations&#xff09; 1. 数学运算 2. 统计计算 3. 张量变形 4. 索引和切片 使用索引访问单个元素 使用切片访问子集 使用索引和…

自动生成bug异常追踪-SRE与开发自动化协同

作者&#xff1a;观测云 数据智能部 产品方案架构师 范莹莹 简介 生产环境 bug 的定义&#xff1a;RUM 应用和 APM 应用的 error_stack 信息被捕捉后成为 bug。 以 APM 新增错误巡检为例&#xff0c;当出现新错误时&#xff0c;在观测云控制台的「事件」模块下生成新的事件报…

Python150题day03

1.2字符串练习题 ①字符串内置方法练习 在交互式解释器中完成下列题目 1.将字符串“abcd"转成大写 2.计算字符串“cd”在 字符串“abcd"中出现的位置 3.字符串“a,b,c,d”&#xff0c;请用逗号分割字符串&#xff0c;分割后的结果是什么类型的&#xff1f; 4."…

Vue2电商前台项目——完成加入购物车功能和购物车页面

Vue2电商前台项目——完成加入购物车功能和购物车页面 文章目录 Vue2电商前台项目——完成加入购物车功能和购物车页面一、加入购物车1、路由跳转前先发请求把商品数据给服务器&#xff08;1&#xff09;观察接口文档&#xff08;2&#xff09;写接口&#xff08;3&#xff09;…

React-Hooks 和 React-Redux

注&#xff1a;Redux最新用法参考 个人React专栏 react 初级学习 Hooks基本介绍------------------------- Hooks&#xff1a;钩子、钓钩、钩住&#xff0c; Hook 就是一个特殊的函数&#xff0c;让你在函数组件中获取状态等 React 特性 &#xff0c;是 React v16.8 中的新增功…

斗地主案例及一些实现规则

4. 斗地主发牌 4.1 案例介绍 按照斗地主的规则&#xff0c;完成洗牌发牌的动作。 具体规则&#xff1a; 使用54张牌打乱顺序,三个玩家参与游戏&#xff0c;三人交替摸牌&#xff0c;每人17张牌&#xff0c;最后三张留作底牌。 4.2 案例分析 准备牌&#xff1a; 牌可以设计为…

机器学习 day34(机器学习项目的完整周期、精确度和召回率、F1)

机器学习项目的完整周期 第一步&#xff0c;决定项目是什么。第二步&#xff0c;收集数据。第三步&#xff0c;训练模型&#xff0c;进行错误分析并改进模型&#xff0c;可能会回到第二步。第四步&#xff0c;当模型足够好后&#xff0c;部署在生产环境中&#xff0c;继续监控…

汽车OTA

汽车OTA&#xff08;Over-The-Air&#xff09;技术是指通过无线网络对汽车进行软件升级、数据传输和远程诊断等功能的技术。随着汽车行业的数字化和智能化发展&#xff0c;OTA技术在汽车领域的应用越来越广泛&#xff0c;对于提高汽车性能、降低维修成本和提升用户体验具有重要…

Leetcode 1004. Max Consecutive Ones III 滑动窗口经典题

Max Consecutive Ones III Medium Given a binary array nums and an integer k, return the maximum number of consecutive 1’s in the array if you can flip at most k 0’s. Example 1: Input: nums [1,1,1,0,0,0,1,1,1,1,0], k 2 Output: 6 Explanation: [1,1,1,0,0…

【Redis7】--3.Redis持久化

Redis持久化 Redis持久化(Redis persistence)是指将数据写入持久化存储&#xff0c;如固态硬盘(SSD) Redis提供了一系列持久化选项&#xff0c;这些包括&#xff1a; RDB(redis数据库)&#xff1a;RDB持久化方式能够在指定的时间间隔对数据进行快照存储AOF(追加文件)&#x…