小工具知识网

当前位置: 首页 > 行业知识 > uniapp+websocket聊天功能实现(超详细!!附代码,可直接复用)

行业知识

uniapp+websocket聊天功能实现(超详细!!附代码,可直接复用)

2026-10-31 18:37:31 来源:互联网转载

���近项目上用到了聊天的功能,下面来分享一下关于websocket,键盘弹出等问题,避免别的朋友踩坑。

先给大家看看效果图 

 接着进入正文了!!!!!

一、需要注意的几个点

1.scroll-view的高度

先看看整体的页面布局

 system.windowHeight : 页面总高度

totalHeight:顶部导航栏高度

sendHeight:底部输入框高度 (设置样式的时候自己设置的)

keyboardHeight:键盘高度(键盘没有弹出的时候为0)

            uni.getSystemInfo({success: res => {this.system = res}})// #ifdef MP-WEIXIN//获取胶囊信息this.menu = uni.getMenuButtonBoundingClientRect()//计算组件高度this.statusBarHeight = this.system.statusBarHeight //状态栏高度this.navigatorHeight = (this.menu.top - this.system.statusBarHeight) * 2 + this.menu.height //导航栏高度this.totalHeight = this.statusBarHeight + this.navigatorHeight //总高度// 保存到全局this.$store.state.totalHeight = this.totalHeightthis.$store.state.system = this.system// #endif// #ifdef APPthis.statusBarHeight = this.system.statusBarHeight //状态栏高度this.navigatorHeight = this.system.statusBarHeight + 45 //导航栏高度this.totalHeight = this.navigatorHeight //总高度// 保存到全局this.$store.state.totalHeight = this.totalHeightthis.$store.state.system = this.system// #endif

这里需要注意的是scroll-view没有高度就和view差不多,scroll-into-view属性就不生效。

2.键盘弹起时,使页面向上移动,顶部导航栏不动

使用textarea原生的键盘弹起时,页面向上移是这样的

 解决后的图片:

 是不是看着顺眼多了

首先的话需要在页面加载的时候监听一下键盘的高度

listenerKeyboardHeight() {this.listener = (res) => {console.log("键盘高度", res.height)this.keyboardHeight = res.heightthis.$nextTick(() => {this.scrollToBottom()})}uni.onKeyboardHeightChange(this.listener)}

当键盘弹出的时候,将scroll-view的高度减去键盘高度,底部发送框向上移动‘键盘高度’的px

底部的发送框一般都是position: fixed;来定位的,将bottom属性变一下就行了

 

3.定位到底部

先再来看看我们的页面布局

最后一条是用于定位到底部的

 

方法:

// 定位到底部scrollToBottom() {this.$nextTick(() => {this.scrollIntoView = "last-msg-item"                // 清空,为下一次定位做准备this.$nextTick(() => {this.scrollIntoView = ""})})},

二、websocket代码

这是封装的一个mixin类

import {socket} from "@/common/mixin/socket.js"//引入方法export default {    mixins: [socket],}

socket.js

export const socket = {data() {return {// socket是否开启socketOpen: false,// 定时器timer: null,// 链接surl: `websocket链接`,// 底部id用于定位到底部scrollIntoView: "",// 键盘高度keyboardHeight: 0,// 监听键盘高度的方法listener: null}},onLoad(option) {// 开启键盘高度监听this.listenerKeyboardHeight()// socket初始化this.init()// 定时器,定时判断socket有没有掉线this.timer = setInterval(() => {this.isSocketConnct()}, 2000)},beforeDestroy() {// 关闭定时器clearInterval(this.timer)// 关闭键盘高度监听uni.offKeyboardHeightChange(this.listener)// 关闭Socketthis.closeSocket()},methods: {// 发送消息sendSocketMessage(msg) {console.log("发送消息", msg);let that = thisif (this.socketOpen) {uni.sendSocketMessage({data: msg,success: (res) => {setTimeout(() => {                            // json转对象let param = JSON.parse(msg)that.sendMessageHandle(param)}, 300)},fail(err) {// 发送失败处理}});} else {// Socket没有开启,重新连接并重新发送消息this.init()setTimeout(() => {this.sendSocketMessage(msg)},300)}},// 判断是否连接isSocketConnct() {if (!this.socketOpen) {console.log("WebSocket 再次连接!");this.init()}},// 初始化init() {this.connect()this.openSocket()this.onclose()this.onSocketMessage()},// 建立连接connect() {console.log(this.surl);uni.connectSocket({url: this.surl,method: 'GET'});},// 监听关闭onclose() {let that = thisuni.onSocketClose((res) => {that.socketOpen = falseconsole.log('WebSocket 已关闭!');});},// 关闭closeSocket() {uni.closeSocket();},// 打开SoceketopenSocket() {let that = thisuni.onSocketOpen((res) => {that.socketOpen = trueconsole.log('WebSocket连接已打开!');});},// 接收事件onSocketMessage() {let that = thisuni.onSocketMessage((res) => {let obj = JSON.parse(res.data)console.log("接收事件", obj);this.onMessageHandle(obj)});},// 接收到事件后处理的方法(可自己重写)onMessageHandle(obj) {// 根据自己业务逻辑重写},// 发送消息后处理的方法(可自己重写)sendMessageHandle(msg) {// 根据自己业务逻辑重写},// 定位到底部scrollToBottom() {this.$nextTick(() => {this.scrollIntoView = "last-msg-item"this.$nextTick(() => {this.scrollIntoView = ""})})},        // 开启键盘高度的监听listenerKeyboardHeight() {this.listener = (res) => {console.log("键盘高度", res.height)this.keyboardHeight = res.heightthis.$nextTick(() => {this.scrollToBottom()})}uni.onKeyboardHeightChange(this.listener)}}}

直接引入就可以使用啦 , 接下来说说几个可能用到的方法,在自己的页面直接用就可以啦

// 发送消息方法send(value) {        // 自定义消息体let param = {"type": 1,"content": value,   }        // 对象转jsonlet m = JSON.stringify(param)this.sendSocketMessage(m)},
// 接收到事件后处理的方法(可自己重写)onMessageHandle(obj) {                   // obj 接收到的事件对象},// 发送消息后处理的方法(可自己重写)sendMessageHandle(msg) {// msg 发送的消息对象}

三、页面布局代码

        {{navbarTitle}}import {mapState} from 'vuex'import {socket} from "@/common/mixin/socket.js"import LkySend from "../component/lky-p-send/lky-p-send.vue"export default {components: {},mixins: [socket],data() {return {src: '',                                // 聊天记录列表messageList: [],                // socket链接,如果在socket.js中改了的话就不用写这个了surl: ``,};},                //  我的高度存在vuex的computed: mapState(["totalHeight", "system", "sendHeight"]),onLoad(option) {// 获取聊天记录this.messageList = uni.getStorageSync(`messageList_${this.$store.state.userInfo.id}`) || []console.log("缓存中的聊天记录", this.messageList);this.scrollToBottom()},methods: {send(value) {let param = {"type": 1,"content": value,}let m = JSON.stringify(param)this.sendSocketMessage(m)},            // 预览图片imageClick(url) {uni.previewImage({urls: [url]})},            // 发送图片imageSend(url) {let param = {"type": 3,"text": "","url": url,"userId": this.$store.state.userInfo.id}let m = JSON.stringify(param)this.sendSocketMessage(m)},            // 发送文件fileSend(url, name) {let param = {"type": 4,"text": name,"url": url,"userId": this.$store.state.userInfo.id}let m = JSON.stringify(param)this.sendSocketMessage(m)},                        // 打开文件openFile(item) {uni.downloadFile({url: item.url,success: (res) => {var filePath = res.tempFilePath;uni.openDocument({filePath: filePath,showMenu: true,success: function(res) {}});}});},// 接收到事件后处理的方法(可自己重写)onMessageHandle(obj) {                //根据业务逻辑重写                // obj接收到的事件},// 发送消息后处理的方法(可自己重写)sendMessageHandle(msg) { //根据业务逻辑重写                // msg 发送的消息},}}body {box-sizing: border-box;padding: 0 ;background-color: $lky-hui-bg ;}.content-box {padding: 0 28rpx;box-sizing: border-box;height: auto;z-index: -1;overflow: hidden;}

到这里一个聊天的功能就结束了 ,这应该已经很详细了,其余的自己根据自己的业务逻辑和ui进行调整就行了!

最后有什么不足的地方也请各位指正优化一下

结束!

上一篇:PHP编辑器全解析,功能亮点与选择指南,助你轻松挑选最佳编辑器!

下一篇:Android Studio插件版本与Gradle 版本对应关系