注:适用版本(Harmony OS NEXT / 5.0 / API 12+ )
一、最终效果预览

二、基础代码结构
javascript
@Entry
@Component
struct ChatApp {
@State messages: Message[] = [] // 所有聊天记录
@State inputText: string = "" // 输入框内容
@State isConnected: boolean = false // 是否在线
private ws: webSocket.WebSocket | null = null
// 建立连接
private connect() {
this.ws = webSocket.createWebSocket()
this.ws.connect('wss://toolin.cn/echo')
// 四个关键监听
this.ws.on('open', () => this.isConnected = true)
this.ws.on('message', (data) => {
this.messages = [...this.messages, new Message('received', data.message)]
})
this.ws.on('close', () => this.isConnected = false)
this.ws.on('error', (err) => console.error('出错啦:', err))
}
// 发送消息
private sendMessage() {
if (this.inputText && this.isConnected) {
this.ws?.send(this.inputText)
this.messages = [...this.messages, new Message('sent', this.inputText)]
this.inputText = ""
}
}
build() { /* 界面代码 */ }
}
三、核心功能
1、连接状态管理
javascript
// 显示连接状态
Text(this.isConnected ? '🟢 在线' : '🔴 离线')
.fontColor(this.isConnected ? Color.Green : Color.Red)
// 连接/断开按钮
Button(this.isConnected ? '断开连接' : '点击连接')
.onClick(() => {
this.isConnected ? this.ws?.close() : this.connect()
})
2、消息收发演示
javascript
// 消息输入框
TextInput({ text: this.inputText, placeholder: '说点什么...'})
.onChange((text) => this.inputText = text)
// 发送按钮
Button('发送')
.onClick(() => this.sendMessage())
// 消息气泡样式
List() {
ForEach(this.messages, (msg) => {
ListItem() {
Text(`${msg.type === 'sent' ? '我' : '对方'}: ${msg.content}`)
.backgroundColor(msg.type === 'sent' ? '#e3f2fd' : '#ffffff')
.padding(10)
.borderRadius(8)
}
})
}
3、自动重连机制(心跳机制)
php
// 简单重连逻辑
private reconnect() {
setTimeout(() => {
console.log('尝试重新连接...')
this.connect()
}, 3000) // 3秒后重试
}
// 在连接断开时触发
this.ws.on('close', () => {
this.isConnected = false
this.reconnect() // 自动重连
})
四**、源码详情**
javascript
import webSocket from '@ohos.net.webSocket' // 导入 WebSocket 模块
import { promptAction } from '@kit.ArkUI' // 导入弹窗模块
export class Message { // 定义消息类
type: 'sent' | 'received' // 消息类型,发送或接收
content: string // 消息内容
timestamp: number // 消息时间戳
constructor(type: 'sent' | 'received', content: string) { // 构造函数
this.type = type // 设置消息类型
this.content = content // 设置消息内容
this.timestamp = new Date().getTime() // 设置当前时间戳
}
}
@Entry // 标记为入口组件
@Component // 标记为组件
struct WebSocketDemo { // 定义 WebSocketDemo 组件
// WebSocket 连接状态
@State isConnected: boolean = false // 初始化为未连接
// 消息输入框内容
@State inputMessage: string = '' // 初始化为空字符串
// 消息记录列表
@State messages: Message[] = [] // 初始化为空数组
// WebSocket 对象
private ws: webSocket.WebSocket | null = null // 初始化为 null
// 初始化 WebSocket
private initWebSocket() {
const wsUrl = 'wss://toolin.cn/echo' // 使用公共测试服务器
try {
this.ws = webSocket.createWebSocket() // 创建 WebSocket 实例
// 注册事件监听
this.ws.on('open', () => { // 监听连接打开事件
this.isConnected = true // 设置连接状态为已连接
this.addMessage('received', '连接已建立') // 添加连接成功消息
})
this.ws.on('message', (data) => { // 监听消息事件
// 检查 data 对象是否包含 message 属性
if (data && data.message) {
this.addMessage('received', `收到消息: ${data.message}`) // 添加收到的消息
} else {
console.error('Received unexpected data:', data) // 输出错误日志
}
})
this.ws.on('close', () => { // 监听连接关闭事件
this.isConnected = false // 设置连接状态为未连接
this.addMessage('received', '连接已关闭') // 添加连接关闭消息
})
this.ws.on('error', (err: Error) => { // 监听错误事件
console.error('WebSocket 错误:', err) // 输出错误日志
this.showAlert(`错误: ${err.message}`) // 显示错误弹窗
})
// 发起连接
this.ws.connect(wsUrl) // 连接到 WebSocket 服务器
} catch (error) {
this.showAlert(`初始化失败: ${error.message}`) // 显示初始化失败弹窗
}
}
// 添加消息到列表
private addMessage(type: 'sent' | 'received', content: string) {
this.messages = [...this.messages, new Message(type, content)] // 将新消息添加到消息列表
}
// 显示弹窗
private async showAlert(message: string) {
const res = await promptAction.showDialog({ // 显示弹窗
title: '提示', // 弹窗标题
message: message, // 弹窗内容
buttons: [ // 弹窗按钮
{ text: '取消', color: '#999999' }, // 取消按钮
{ text: '确定', color: '#007aff' } // 确定按钮
]
})
}
build() {
Column() { // 垂直布局
// 连接状态显示
Text(this.isConnected ? '已连接' : '未连接') // 显示连接状态
.fontColor(this.isConnected ? Color.Green : Color.Red) // 设置字体颜色
.margin(10) // 设置外边距
// 控制按钮
Row() { // 水平布局
Button(this.isConnected ? '断开连接' : '建立连接') // 根据连接状态显示按钮文本
.onClick(() => { // 点击事件处理
if (this.isConnected) {
this.ws?.close() // 关闭 WebSocket 连接
this.ws = null // 将 WebSocket 对象设置为 null
} else {
this.initWebSocket() // 初始化 WebSocket 连接
}
})
.margin(5) // 设置外边距
Button('清空记录') // 清空记录按钮
.onClick(() => this.messages = []) // 清空消息列表
.margin(5) // 设置外边距
}
// 消息输入区
TextInput({ text: this.inputMessage,placeholder:'请输入消息'}) // 文本输入框
.onChange((value: string) => this.inputMessage = value) // 输入内容变化时更新 inputMessage
.margin(10) // 设置外边距
.height(60) // 设置高度
.width('90%') // 设置宽度
Button('发送消息') // 发送消息按钮
.onClick(() => { // 点击事件处理
if (this.inputMessage.trim() && this.isConnected) { // 检查输入内容和连接状态
this.ws?.send(this.inputMessage) // 发送消息
this.addMessage('sent', this.inputMessage) // 添加发送的消息
this.inputMessage = '' // 清空输入框
}
})
.margin(10) // 设置外边距
// 消息记录列表
List({ space: 10 }) { // 列表布局
ForEach(this.messages, (msg: Message) => { // 遍历消息列表
ListItem() { // 列表项
Column() { // 垂直布局
Text(`${msg.type === 'sent' ? '[发送]' : '[接收]'} ${msg.content}`) // 显示消息类型和内容
.fontSize(14) // 设置字体大小
.fontColor(msg.type === 'sent' ? Color.Blue : Color.Gray) // 设置字体颜色
Text(new Date(msg.timestamp).toLocaleTimeString()) // 显示消息时间
.fontSize(10) // 设置字体大小
.fontColor(Color.Gray) // 设置字体颜色
}
.padding(10) // 设置内边距
.width('100%') // 设置宽度
.alignItems(msg.type === 'sent' ? HorizontalAlign.End : HorizontalAlign.Start) // 设置对齐方式
}
})
}
.layoutWeight(1) // 设置布局权重
.divider({ strokeWidth: 1, color: '#eee' }) // 设置分隔线
}
.width('100%') // 设置宽度
.height('100%') // 设置高度
.padding(10) // 设置内边距
.backgroundColor('#f0f0f0') // 设置背景颜色
}
}
五、问题优化
1、权限配置问题
存在原因:
网络请求失败
控制台报错PERMISSION_DENIED
解决方法:module.josn5配置文件中配置网络权限
javascript
// module.json5 配置
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
}
]
2、 消息安全性风险
javascript
// 消息内容过滤
private sanitizeMessage(content: string): string {
return content
.replace(/</g, '<')
.replace(/>/g, '>')
.substring(0, 500); // 限制消息长度
}
3. 防止频繁发送
javascript
private lastSendTime: number = 0
sendMessage() {
if (Date.now() - this.lastSendTime < 1000) {
promptAction.showToast({ message: '发送太频繁啦!' })
return
}
// ...正常发送逻辑
this.lastSendTime = Date.now()
}
五、总结
-
测试地址 :先用
wss://echo.websocket.org
这种公共测试服务 -
真机调试:记得在手机设置里打开应用的网络权限
-
基础样式:先实现功能再美化界面
-
错误处理:关键操作添加try-catch防止崩溃
通过这个简化版,开发者可以快速搭建基础聊天功能,再逐步添加进阶特性。建议先跑通基础代码,再按需扩展功能!